所有分类
  • 所有分类
  • 未分类

Jackson–配置方法/实例

简介

本文介绍Jackson的配置方式。(配置ObjectMapper)。

配置示例

ObjectMapper objectMapper = new ObjectMapper();

// 反序列化:JSON字段中有Java对象中没有的字段时不报错
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

// 反序列化:不允许基本类型为null
//objectMapper.configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, true);

// 序列化:序列化BigDecimal时不使用科学计数法输出
objectMapper.configure(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN, true);

// 序列化:Java对象为空的字段不拼接JSON
//objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

反序列化的配置

忽略未知的JSON字段

有时候,Java对象的字段比JSON字符串中的字段少。 默认情况下,Jackson会抛出异常,报不知道xxx字段异常,因为在Java对象中找不到该字段。

大多数情况下,我们想允许JSON中的字段多于相应的Java对象中的字段。 例如,要从REST服务解析JSON,而该REST服务包含的数据远远超出所需的。 在这种情况下,可以使用Jackson配置忽略这些额外的字段。

objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

不允许基本类型为null

简介

将JSON字符串转为Java对象时,如果JSON字符串值为null的字段对应Java对象的基本数据类型(int,long,float,double等),Jackson默认会将这个字段设置为初始值,比如:对于int,则将其设置为0。

我们可以进行自定义配置:基本数据为null让其报错,转换失败。

实例:默认情况

Entity

package com.example.entity;

import lombok.Data;

@Data
public class User {
    private String userName;
    private int age;
}

Controller

package com.example.controller;

import com.example.entity.User;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    @GetMapping("/test")
    public String test() throws JsonProcessingException {
        String json = "{\"userName\":\"Tony\", \"age\":null}";
        ObjectMapper objectMapper = new ObjectMapper();
        User user = objectMapper.readValue(json, User.class);
        System.out.println(user);

        return "test success";
    }
}

测试

访问:http://localhost:8080/test

后端结果:

实例:修改配置

Entity

package com.example.entity;

import lombok.Data;

@Data
public class User {
    private String userName;
    private int age;
}

Controller

package com.example.controller;

import com.example.entity.User;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    @GetMapping("/test")
    public String test() throws JsonProcessingException {
        String json = "{\"userName\":\"Tony\", \"age\":null}";
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, true);
        User user = objectMapper.readValue(json, User.class);
        System.out.println(user);

        return "test success";
    }
}

测试

访问:http://localhost:8080/test

后端结果

2021-09-18 22:12:46.132 ERROR 22264 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception

com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot map `null` into type int (set DeserializationConfig.DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES to 'false' to allow)
 at [Source: (String)"{"userName":"Tony", "age":null}"; line: 1, column: 27] (through reference chain: com.example.entity.User["age"])
	at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63) ~[jackson-databind-2.11.0.jar:2.11.0]
	at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1438) ~[jackson-databind-2.11.0.jar:2.11.0]
	at com.fasterxml.jackson.databind.deser.std.NumberDeserializers$PrimitiveOrWrapperDeserializer.getNullValue(NumberDeserializers.java:161) ~[jackson-databind-2.11.0.jar:2.11.0]
	at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:127) ~[jackson-databind-2.11.0.jar:2.11.0]
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:293) ~[jackson-databind-2.11.0.jar:2.11.0]
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:156) ~[jackson-databind-2.11.0.jar:2.11.0]
	at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4482) ~[jackson-databind-2.11.0.jar:2.11.0]
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3434) ~[jackson-databind-2.11.0.jar:2.11.0]
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3402) ~[jackson-databind-2.11.0.jar:2.11.0]
	at com.example.controller.HelloController.test(HelloController.java:18) ~[classes/:na]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_201]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_201]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_201]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_201]
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) ~[spring-web-5.2.6.RELEASE.jar:5.2.6.RELEASE]
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) ~[spring-web-5.2.6.RELEASE.jar:5.2.6.RELEASE]
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105) ~[spring-webmvc-5.2.6.RELEASE.jar:5.2.6.RELEASE]
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:879) ~[spring-webmvc-5.2.6.RELEASE.jar:5.2.6.RELEASE]
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:793) ~[spring-webmvc-5.2.6.RELEASE.jar:5.2.6.RELEASE]
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.2.6.RELEASE.jar:5.2.6.RELEASE]
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040) ~[spring-webmvc-5.2.6.RELEASE.jar:5.2.6.RELEASE]
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) ~[spring-webmvc-5.2.6.RELEASE.jar:5.2.6.RELEASE]
	...
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.35.jar:9.0.35]
	at java.lang.Thread.run(Thread.java:748) [na:1.8.0_201]

自定义反序列化

可以将自定义反序列化器添加到ObjectMapper。

在Jackson的ObjectMapper中注册和使用自定义反序列化器的方式:

String json = "{\"userName\": \"Tony\", \"age\" : 22 }";

SimpleModule module = new SimpleModule("UserDeserializer", new Version(3, 1, 8, null, null, null));
module.addDeserializer(User.class, new UserDeserializer(User.class));

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(module);

User user = mapper.readValue(json, User.class);

自定义反序列化器UserDeserializer类:

public class UserDeserializer extends StdDeserializer<User> {

    public UserDeserializer(Class<?> vc) {
        super(vc);
    }

    @Override
    public User deserialize(JsonParser parser, DeserializationContext deserializer) throws IOException {
        User user = new User();
        while(!parser.isClosed()){
            JsonToken jsonToken = parser.nextToken();

            if(JsonToken.FIELD_NAME.equals(jsonToken)){
                String fieldName = parser.getCurrentName();
                System.out.println(fieldName);

                jsonToken = parser.nextToken();

                if("userName".equals(fieldName)){
                    user.setUserName(parser.getValueAsString());
                } else if ("age".equals(fieldName)){
                    user.setAge(parser.getValueAsInt());
                }
            }
        }
        return user;
    }
}
0

评论0

请先

显示验证码
没有账号?注册  忘记密码?

社交账号快速登录