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

我有一个对象,有时看起来像这样:


{

   "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;

}


如何编写一个自定义反序列化程序(或其他一些模块)来一般处理这两种情况?


猛跑小猪
浏览 120回答 1
1回答

GCT1015

为了使其通用,我们需要能够指定要在对象中为 设置的名称。一定的灵活性提供了注释方法。让我们定义简单的注释:JSON primitive@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.FIELD)@interface JsonPrimitiveName {&nbsp; &nbsp; String value();}名称的意思是:如果基元将出现在使用中获取给定基元的属性名称。它与字段绑定。简单的去铈化器,可处理和:JSONvalue()JSON primitivePOJOJSON objectJSON primitiveclass PrimitiveOrPojoJsonDeserializer extends JsonDeserializer implements ContextualDeserializer {&nbsp; &nbsp; private String primitiveName;&nbsp; &nbsp; private JavaType type;&nbsp; &nbsp; @Override&nbsp; &nbsp; public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {&nbsp; &nbsp; &nbsp; &nbsp; JsonDeserializer<Object> deserializer = ctxt.findRootValueDeserializer(type);&nbsp; &nbsp; &nbsp; &nbsp; if (p.currentToken() == JsonToken.START_OBJECT) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return deserializer.deserialize(p, ctxt);&nbsp; &nbsp; &nbsp; &nbsp; } else if (p.currentToken() == JsonToken.VALUE_STRING) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; BeanDeserializer beanDeserializer = (BeanDeserializer) deserializer;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Object instance = beanDeserializer.getValueInstantiator().getDefaultCreator().call();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SettableBeanProperty property = beanDeserializer.findProperty(primitiveName);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; property.deserializeAndSet(p, ctxt, instance);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return instance;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } catch (Exception e) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw JsonMappingException.from(p, e.getMessage());&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; return null;&nbsp; &nbsp; }&nbsp; &nbsp; @Override&nbsp; &nbsp; public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property) {&nbsp; &nbsp; &nbsp; &nbsp; JsonPrimitiveName annotation = property.getAnnotation(JsonPrimitiveName.class);&nbsp; &nbsp; &nbsp; &nbsp; PrimitiveOrPojoJsonDeserializer deserializer = new PrimitiveOrPojoJsonDeserializer();&nbsp; &nbsp; &nbsp; &nbsp; deserializer.primitiveName = annotation.value();&nbsp; &nbsp; &nbsp; &nbsp; deserializer.type = property.getType();&nbsp; &nbsp; &nbsp; &nbsp; return deserializer;&nbsp; &nbsp; }}现在我们需要按如下方式对字段进行注释:POJOclass Root {&nbsp; &nbsp; @JsonPrimitiveName("value")&nbsp; &nbsp; @JsonDeserialize(using = PrimitiveOrPojoJsonDeserializer.class)&nbsp; &nbsp; private Foo foo;&nbsp; &nbsp; @JsonPrimitiveName("thing")&nbsp; &nbsp; @JsonDeserialize(using = PrimitiveOrPojoJsonDeserializer.class)&nbsp; &nbsp; private Fuzz fuzz;&nbsp; &nbsp; // 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 {&nbsp; &nbsp; public static void main(String[] args) throws Exception {&nbsp; &nbsp; &nbsp; &nbsp; File jsonFile = new File("./resource/test.json").getAbsoluteFile();&nbsp; &nbsp; &nbsp; &nbsp; ObjectMapper mapper = new ObjectMapper();&nbsp; &nbsp; &nbsp; &nbsp; System.out.println(mapper.readValue(jsonFile, Root.class));&nbsp; &nbsp; }}打印缩短 :JSONRoot{foo=Foo{value='bar', baz='null'}, fuzz=Fuzz{thing='bla', blip='null'}}对于完整有效载荷:JSONRoot{foo=Foo{value='bar', baz='asdf'}, fuzz=Fuzz{thing='bla', blip='asdf'}}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java