![](/img/trans.png)
[英]Deserialize a Jackson serialized object to Map<String, Object>?
[英]Deserialize to String or Object using Jackson
我有一個有時看起來像這樣的對象:
{
"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;
}
第一種情況是第二種情況的簡寫。 我想總是反序列化到第二種情況。
進一步 - 這是我們代碼中非常常見的模式,所以我希望能夠以通用方式進行序列化,因為上面有類似於Foo
其他類具有使用String作為語法糖的相同模式一個更復雜的對象。
我想像使用它的代碼看起來像這樣
public class Thing {
@JsonProperty("fuzz")
Fuzz fuzz;
@JsonProperty("foo")
Foo foo;
}
如何編寫通常處理這兩種情況的自定義反序列化器(或其他模塊)?
為了使它通用,我們需要能夠指定我們想要在JSON primitive
對象中設置的名稱。 一些靈活性給出了注釋方法。 讓我們定義簡單的注釋:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@interface JsonPrimitiveName {
String value();
}
名稱表示:如果原語將出現在JSON
使用value()
來獲取給定基元的屬性名稱。 它將JSON primitive
與POJO
字段綁定。 處理JSON object
和JSON 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
}
我假設所有類都是POJO
並遵循所有規則 - 有getters
, setters
和默認構造函數。 如果構造函數不存在,您需要以某種方式更改此beanDeserializer.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'}}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.