2016-03-03 28 views
8

Biorąc pod uwagę moją własną implementację macierzy MyArray<T>, w jaki sposób mogę ją przekazać Jacksonowi, aby mogła przekształcić się z macierzy JSON w MyArray<T>? Do tej pory ja dostaję tylko ten wyjątek:Jak przekonwertować Jackson do postaci szeregowej na moją własną implementację Array?

com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of MyArray out of START_ARRAY token 
+8

więcej kodu, opublikować 'MyArray' klasę. – Dariusz

+0

Jest to implementacja Arduino LibGDX: https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/utils/Array.java – tyrondis

+0

również tam, gdzie deserializacja może być – valepu

Odpowiedz

2

Jak wspomniał Dariusz, dobrze jest skorzystać z tego, że klasa Array ma konstruktor akceptujący normalną tablicę.

Look, jeśli użyjesz domyślnego serializatora - Twoja tablica szeregowane do JSON wyglądałby następująco:

{"items":["item1","item2"],"size":2,"ordered":true} 

to wyraźnie marnowanie miejsca, chyba że chcesz size i ordered pola mają być zachowane.

Proponuję zmienić sposób serializowania obiektu, aby wyglądał bardziej jak zwykła tablica, na drugim końcu - deserializacja może ponownie zbudować obiekt Array.

Jeśli dodać następne parę serializatora i Deserializatora:

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

będziesz miał przejrzystą konwersję pomiędzy tymi typami są potrzebne

+0

Dzięki! Najbardziej lubię ten. – tyrondis

2

Klasa Array z libgdx ma konstruktora, który akceptuje tablicę: public Array (T[] array).

Zamiast próbować serializować tablicę libgdx użyj prostej klasy z tablicą jako bazy do serializacji/desrializacji, a następnie utwórz tablicę libgdx na podstawie deserializowanych danych.

Generalnie jest to dobra zasada do serializowania tylko obiektów typu POJO.

W skrócie:

{ 
    //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! 
} 
+0

To właśnie robię teraz, jednak pomyślałem, że byłoby bardziej elegancko korzystać z tablicy LibGDX bezpośrednio, zamiast konwertować tam iz powrotem. – tyrondis

+1

Będziesz musiał zmodyfikować kod dla tablicy libgdx, jak sądzę - zaznacz tylko niestandardowe metody serializacji z odpowiednimi adnotacjami. Lub użyj XmlAdapter, Myślę, że działa dla json, nie jestem jednak pewien. – Dariusz

1

Jednym ze sposobów, aby to zrobić jest napisanie serializatora jak

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(); 
    } 
} 

a Deserializator jak

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 
    } 
} 

Następnie opisywanie właściwość, która posiada takie tablica z @JsonSerialize(using = MyArraySerializer.class) @JsonDeserialize(using = MyArrayDeserializer.class).
Jeśli używasz implementacji tablicy bezpośrednio, zamiast wewnątrz klasy pojemnika, ta strona ma przykład jak zarejestrować teleskopowe serializacji w czasie wykonywania http://wiki.fasterxml.com/JacksonHowToCustomSerializers

Należy zauważyć, że w tej odpowiedzi Używam Jackson 1,9 API i 2.x mogą się nieznacznie różnić. Według http://wiki.fasterxml.com/JacksonUpgradeFrom19To20 najbardziej zauważalnymi różnicami są zmiany w nazwach pakietów i lokalizacja niektórych klas. W przeciwnym razie kod ten nie powinien ulec zmianie.