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有效,但我不确定。谢谢!我最喜欢这个。