Java 如何让Jackson反序列化到我自己的数组实现中
给定我自己的数组实现Java 如何让Jackson反序列化到我自己的数组实现中,java,json,jackson,json-deserialization,Java,Json,Jackson,Json Deserialization,给定我自己的数组实现MyArray,我如何让Jackson知道它,以便它能够从JSON数组反序列化到MyArray?到目前为止,我只得到一个例外: com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of MyArray out of START_ARRAY token libgdx中的Array类有一个接受数组的构造函数:公共数组(T[]Array) 与其尝试序列化libgdx数组
MyArray
,我如何让Jackson知道它,以便它能够从JSON数组反序列化到MyArray
?到目前为止,我只得到一个例外:
com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of MyArray out of START_ARRAY token
libgdx中的Array类有一个接受数组的构造函数:
公共数组(T[]Array)
与其尝试序列化libgdx数组,不如使用带有数组的简单类作为序列化/反序列化的基础,然后基于反序列化数据创建libgdx数组
通常,只序列化POJO类型的对象是一个好规则
简言之:
{
//serialize:
com.badlogic.gdx.utils.Array<MyObj> arr = ...;
MyObj[] myArr = arr.toArray();
MyCustomContainer cont = new MyCustomContainer(myArr);
String serializedData = mapper.writeValueAsString(cont);
// do sth with the data
}
{
//deserialize
MyCusomContainer cont = mapper.readValue(..., MyCustomContainer.class);
com.badlogic.gdx.utils.Array<MyObj> arr = new com.badlogic.gdx.utils.Array<MyObj>(cont.getArray());
// done!
}
{
//序列化:
com.badlogic.gdx.utils.Array arr=。。。;
MyObj[]myArr=arr.toArray();
MyCustomContainer cont=新的MyCustomContainer(myArr);
String serializedData=mapper.writeValueAsString(续);
//用数据做某事
}
{
//反序列化
MyCusomContainer cont=mapper.readValue(…,MyCustomContainer.class);
com.badlogic.gdx.utils.Array arr=new com.badlogic.gdx.utils.Array(cont.getArray());
//完成了!
}
一种方法是编写一个序列化程序,如
import java.io.IOException;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.map.SerializerProvider;
import org.codehaus.jackson.map.ser.std.SerializerBase;
public class MyArraySerializer extends SerializerBase<MyArray> {
protected MyArraySerializer() {
super(MyArray.class);
}
@Override
public void serialize(MyArray myArray, JsonGenerator gen, SerializerProvider p)
throws IOException, JsonGenerationException {
gen.writeStartArray();
Iterator<MyObject> it = myArray.iterator();
while (it.hasNext()) {
MyObject ob = it.next();
gen.writeObject(p);
if (it.hasNext()) {
gen.writeRaw(',');
}
}
gen.writeEndArray();
}
}
import java.io.IOException;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.DeserializationContext;
import org.codehaus.jackson.map.JsonDeserializer;
public class MyArrayDeserializer extends JsonDeserializer<MyArray> {
@Override
public MyArray deserialize(JsonParser parser, DeserializationContext ctx)
throws IOException, JsonProcessingException {
MyObject[] obs = parser.readValueAs(MyObject[].class);
return new MyArray(obs); //presuming you have a copy-constructor
}
}
import java.io.IOException;
导入org.codehaus.jackson.jsongGenerationException;
导入org.codehaus.jackson.jsonggenerator;
导入org.codehaus.jackson.map.SerializerProvider;
导入org.codehaus.jackson.map.ser.std.rbase;
公共类MyArraySerializer扩展SerializerBase{
受保护的MyArraySerializer(){
super(MyArray.class);
}
@凌驾
公共void序列化(MyArray MyArray、JsonGenerator gen、SerializerProvider p)
抛出IOException、JsonGenerationException{
WriteStartaray将军();
迭代器it=myArray.Iterator();
while(it.hasNext()){
MyObject ob=it.next();
gen.writeObject(p);
if(it.hasNext()){
gen.writeRaw(',');
}
}
writeEndArray将军();
}
}
还有像这样的反序列化程序
import java.io.IOException;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.map.SerializerProvider;
import org.codehaus.jackson.map.ser.std.SerializerBase;
public class MyArraySerializer extends SerializerBase<MyArray> {
protected MyArraySerializer() {
super(MyArray.class);
}
@Override
public void serialize(MyArray myArray, JsonGenerator gen, SerializerProvider p)
throws IOException, JsonGenerationException {
gen.writeStartArray();
Iterator<MyObject> it = myArray.iterator();
while (it.hasNext()) {
MyObject ob = it.next();
gen.writeObject(p);
if (it.hasNext()) {
gen.writeRaw(',');
}
}
gen.writeEndArray();
}
}
import java.io.IOException;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.DeserializationContext;
import org.codehaus.jackson.map.JsonDeserializer;
public class MyArrayDeserializer extends JsonDeserializer<MyArray> {
@Override
public MyArray deserialize(JsonParser parser, DeserializationContext ctx)
throws IOException, JsonProcessingException {
MyObject[] obs = parser.readValueAs(MyObject[].class);
return new MyArray(obs); //presuming you have a copy-constructor
}
}
import java.io.IOException;
导入org.codehaus.jackson.JsonParser;
导入org.codehaus.jackson.JsonProcessingException;
导入org.codehaus.jackson.map.DeserializationContext;
导入org.codehaus.jackson.map.jsonderializer;
公共类MyArraydSerializer扩展JsonDeserializer{
@凌驾
公共MyArray反序列化(JsonParser解析器,反序列化上下文ctx)
抛出IOException、JsonProcessingException{
MyObject[]obs=parser.readValueAs(MyObject[]类);
返回新的MyArray(obs);//假定您有一个副本构造函数
}
}
然后用@JsonSerialize(使用=MyArraySerializer.class)@jsondesellize(使用=myarraydesellizer.class)
注释保存这样一个数组的属性
如果直接使用数组实现,而不是在容器类中使用,则本页提供了如何在运行时注册序列化处理程序的示例
我应该注意,在这个回答中,我使用的是Jackson1.9API,而2.x可能略有不同。最明显的区别是包名和某些类所在位置的变化。否则这段代码应该不受影响。正如Dariusz提到的,最好利用
Array
类的构造函数接受普通数组这一事实
看,如果使用默认序列化程序,则序列化为JSON的数组如下所示:
{"items":["item1","item2"],"size":2,"ordered":true}
这显然是浪费空间,除非您希望保留size
和ordered
字段
我建议您改变序列化对象的方式,使其看起来更像普通数组,另一方面,反序列化可以再次构建array
对象
如果添加以下一对序列化程序和反序列化程序:
SimpleModule module = new SimpleModule();
module.addDeserializer(Array.class, new StdDelegatingDeserializer<>(
new StdConverter<Object[], Array>() {
@Override
public Array convert(Object[] value) {
return new Array(value);
}
}));
module.addSerializer(Array.class, new StdDelegatingSerializer(
new StdConverter<Array, Object>() {
@Override
public Object convert(Array value) {
return value.toArray();
}
}));
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(module);
SimpleModule=newsimpleModule();
module.addDeserializer(Array.class,新StdDelegatingDeserializer(
新的StdConverter(){
@凌驾
公共数组转换(对象[]值){
返回新数组(值);
}
}));
module.addSerializer(Array.class,新StdDelegatingSerializer(
新的StdConverter(){
@凌驾
公共对象转换(数组值){
返回值.toArray();
}
}));
ObjectMapper mapper=新的ObjectMapper();
映射器注册表模块(模块);
您将在这些类型之间进行透明转换需要更多代码,发布
MyArray
类。这是LibGDX的数组实现:反序列化发生的地方可能是@Dariusz怀疑我做了同样的事情。问题在于,您的类不扩展数组,而是将数组作为实例变量,这是数组操作发生的地方。您的JSON必须反映MyArray的结构(一个包含数组的对象可能会工作)。我想这就是问题所在,我不知道是否有什么方法可以告诉Jackson把你的类当作一个数组来对待(但我希望有人能给你答案),你可以为Jackson编写你的自定义反序列化程序。虽然我从未尝试过使用自定义数组,但它也应该可以工作。这就是我现在正在做的,但是我认为直接使用LibGDX数组会更优雅,而不是来回转换。您必须修改LibGDX数组的代码,我猜-只标记带有适当注释的用于序列化的自定义方法。或者使用XmlAdapter,我想它对json有效,但我不确定。谢谢!我最喜欢这个。