Json反序列化之ObjectMapper(自定义实现反序列化方法)

本文介绍了如何使用ObjectMapper进行Json反序列化,并针对第三方接口返回数据类型不一致的问题,提出了两种解决方案:1. 在bean的set方法内进行判断处理;2. 继承JsonDeserializer,自定义反序列化方法。详细解析了Json反序列化过程,包括JsonParser、JavaType的获取,以及BeanDeserializer的工作原理。
摘要由CSDN通过智能技术生成

本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/50868105



     对于服务器端开发人员而言,调用第三方接口获取数据,将其“代理”转化并返给客户端几乎是家常便饭的事儿。    一般情况下,第三方接口返回的数据类型是json格式,而服务器开发人员则需将json格式的数据转换成对象,继而对其进行处理并封装,以返回给客户端。

     在不是特别考虑效率的情况下(对于搜索、缓存等情形可以考虑使用thrift和protobuffer),通常我们会选取jackson包中的ObjectMapper类对json串反序列化以得到相应对象。通常会选取readValue(String content, Class<T>valueType)方法进行反序列化。

     ObjectMapper的readValue方法将json串反序列化为对象的过程大致为: 依据传入的json串和目标对象类型分别创建JsonParse和JavaType,随后生成DeserializationConfig、DeserializationContext、JsonDeserializer,其中JsonDeserializer的实现类决定将要执行哪一种类型解析(Bean、Map、String等),JsonParse中存储了待解析字符串及其它信息,在解析的过程中通过token来判断当前匹配的类型(例如:如果遇到{,将其判断为对象类型的起始位置;遇到[,将其判断为集合类型的起始位置),一旦确定了类型,则跳入与之对应的反序列化类中进行处理,得到结果,然后token往后移动,接着解析下一个串。可以看做类似递归的方式进行解析,当通过token判断为一个对象时,则会跳入BeanDeserializer中进行解析,随后遍历该对象的所有字段,如果字段是字符串,则跳到StringDeserializer中进行解析,如果字段是数组,则跳到CollectionDeserializer中进行解析,直到解析完整个字符串为止。也可以看做类似而树的深度遍历,理解起来还是挺容易的。


下面将简单介绍ObjectMapper的readValue方法进行反序列化的过程:
a:通过json串和对象类型得到JsonParser和JavaType。

    public <T> T readValue(String content, Class<T> valueType)
        throws IOException, JsonParseException, JsonMappingException
    {
        return (T) _readMapAndClose(_jsonFactory.createParser(content), _typeFactory.constructType(valueType));
    } 

    //获取json解析器,其中包含带解析的串
    public JsonParser createParser(String content) throws IOException, JsonParseException {
        final int strLen = content.length();
        // Actually, let's use this for medium-sized content, up to 64kB chunk (32kb char)
        if (_inputDecorator != null || strLen > 0x8000 || !canUseCharArrays()) {
            // easier to just wrap in a Reader than extend InputDecorator; or, if content
            // is too long for us to copy it over
            return createParser(new StringReader(content));
        }
        IOContext ctxt = _createContext(content, true);
        char[] buf = ctxt.allocTokenBuffer(strLen);
        content.getChars(0, strLen, buf, 0);
        return _createParser(buf, 0, strLen, ctxt, true);
  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
ObjectMapper是一个提供了对象序列化和反序列化功能的Java库。默认情况下,ObjectMapper会通过对象的Getter方法来访问对象的属性,并将其序列化为JSON格式的字符串。 然而,在某些情况下,我们可能希望自定义对象的序列化方式。为了实现自定义序列化,我们可以通过ObjectMapper的配置来改变它的行为。 首先,我们可以使用@JsonSerialize注解来标记需要自定义序列化的属性。我们可以在注解中指定一个自定义的序列化器类,该类需要继承JsonSerializer类,并且实现serialize方法,这个方法定义了如何将属性序列化为JSON字符串的逻辑。 例如,假设我们有一个User类,其中有一个属性名为password,我们希望在序列化时将其隐藏起来: ```java public class User { private String username; private String password; // 省略构造方法和Getter/Setter @JsonSerialize(using = CustomPasswordSerializer.class) public String getPassword() { return password; } } public class CustomPasswordSerializer extends JsonSerializer<String> { @Override public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException { gen.writeString("********"); // 替换真实密码的序列化逻辑 } } ``` 上面的例子中,我们通过@JsonSerialize注解自定义了User类中的password属性的序列化方式,使用了CustomPasswordSerializer类进行序列化。 然后,我们需要创建一个ObjectMapper实例,并将其注册到注解的Module中: ```java ObjectMapper objectMapper = new ObjectMapper(); SimpleModule module = new SimpleModule(); module.addSerializer(CustomPasswordSerializer.class, new CustomPasswordSerializer()); objectMapper.registerModule(module); ``` 最后,我们可以使用定制的ObjectMapper来进行对象的序列化操作: ```java User user = new User("admin", "password"); String jsonString = objectMapper.writeValueAsString(user); System.out.println(jsonString); ``` 通过以上配置,我们可以看到在User对象序列化时,password属性的值将会被替换为"********"。这样,我们就实现了对ObjectMapper自定义序列化。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值