为了账号安全,请及时绑定邮箱和手机立即绑定

使用杰克逊反序列化为字符串或对象

使用杰克逊反序列化为字符串或对象

猛跑小猪 2022-09-14 15:18:19
我有一个对象,有时看起来像这样:{   "foo" : "bar",   "fuzz" : "bla"}有时看起来像这样:{   "foo" : { "value" : "bar", "baz": "asdf" },   "fuzz" : { "thing" : "bla", "blip" : "asdf" }}这些类将如下所示:public class Foo {   String value;   String baz;}public class Fuzz {   String thing;   String blip;}其中第一种情况是第二种情况的简写。我想始终反序列化到第二种情况。此外 - 这是我们代码中非常常见的模式,所以我希望能够以通用方式进行序列化,因为还有其他类似于上面的类具有相同的模式,即使用String作为更复杂的对象的语法糖。Foo我想象使用它的代码看起来像这样public class Thing {   @JsonProperty("fuzz")  Fuzz fuzz;  @JsonProperty("foo")  Foo foo;}如何编写一个自定义反序列化程序(或其他一些模块)来一般处理这两种情况?
查看完整描述

1 回答

?
GCT1015

TA贡献1827条经验 获得超4个赞

为了使其通用,我们需要能够指定要在对象中为 设置的名称。一定的灵活性提供了注释方法。让我们定义简单的注释:JSON primitive


@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.FIELD)

@interface JsonPrimitiveName {

    String value();

}

名称的意思是:如果基元将出现在使用中获取给定基元的属性名称。它与字段绑定。简单的去铈化器,可处理和:JSONvalue()JSON primitivePOJOJSON objectJSON primitive


class PrimitiveOrPojoJsonDeserializer extends JsonDeserializer implements ContextualDeserializer {


    private String primitiveName;

    private JavaType type;


    @Override

    public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {

        JsonDeserializer<Object> deserializer = ctxt.findRootValueDeserializer(type);

        if (p.currentToken() == JsonToken.START_OBJECT) {

            return deserializer.deserialize(p, ctxt);

        } else if (p.currentToken() == JsonToken.VALUE_STRING) {

            BeanDeserializer beanDeserializer = (BeanDeserializer) deserializer;

            try {

                Object instance = beanDeserializer.getValueInstantiator().getDefaultCreator().call();

                SettableBeanProperty property = beanDeserializer.findProperty(primitiveName);

                property.deserializeAndSet(p, ctxt, instance);

                return instance;

            } catch (Exception e) {

                throw JsonMappingException.from(p, e.getMessage());

            }

        }


        return null;

    }


    @Override

    public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property) {

        JsonPrimitiveName annotation = property.getAnnotation(JsonPrimitiveName.class);


        PrimitiveOrPojoJsonDeserializer deserializer = new PrimitiveOrPojoJsonDeserializer();

        deserializer.primitiveName = annotation.value();

        deserializer.type = property.getType();


        return deserializer;

    }

}

现在我们需要按如下方式对字段进行注释:POJO


class Root {


    @JsonPrimitiveName("value")

    @JsonDeserialize(using = PrimitiveOrPojoJsonDeserializer.class)

    private Foo foo;


    @JsonPrimitiveName("thing")

    @JsonDeserialize(using = PrimitiveOrPojoJsonDeserializer.class)

    private Fuzz fuzz;


    // getters, setters

}

我假设所有类都是 -s 并遵循所有规则 - have 和默认构造函数。如果构造函数不存在,您需要以某种方式更改此行以符合您的要求。POJOgetterssettersbeanDeserializer.getValueInstantiator().getDefaultCreator().call()


示例应用:


import com.fasterxml.jackson.core.JsonParser;

import com.fasterxml.jackson.core.JsonToken;

import com.fasterxml.jackson.databind.BeanProperty;

import com.fasterxml.jackson.databind.DeserializationContext;

import com.fasterxml.jackson.databind.JavaType;

import com.fasterxml.jackson.databind.JsonDeserializer;

import com.fasterxml.jackson.databind.JsonMappingException;

import com.fasterxml.jackson.databind.ObjectMapper;

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;

import com.fasterxml.jackson.databind.deser.BeanDeserializer;

import com.fasterxml.jackson.databind.deser.ContextualDeserializer;

import com.fasterxml.jackson.databind.deser.SettableBeanProperty;


import java.io.File;

import java.io.IOException;

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;


public class JsonApp {


    public static void main(String[] args) throws Exception {

        File jsonFile = new File("./resource/test.json").getAbsoluteFile();


        ObjectMapper mapper = new ObjectMapper();

        System.out.println(mapper.readValue(jsonFile, Root.class));

    }

}

打印缩短 :JSON


Root{foo=Foo{value='bar', baz='null'}, fuzz=Fuzz{thing='bla', blip='null'}}

对于完整有效载荷:JSON


Root{foo=Foo{value='bar', baz='asdf'}, fuzz=Fuzz{thing='bla', blip='asdf'}}


查看完整回答
反对 回复 2022-09-14
  • 1 回答
  • 0 关注
  • 119 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信