2014-10-31 6 views
8

Dies ist Jackson 2.2.x.Wie können Aufrufe von .serializeWithType() einer Klasse ausgelöst werden, die JsonSerializable in Jackson implementiert?

Ich habe eine Klasse implementieren JsonSerializable; Es gibt zwei Methoden, die für diese Schnittstelle implementiert werden können: und serializeWithType().

Ich möchte {de} Serialisierung dieser Klasse testen, und ich kann Anrufe auf leicht auslösen; nicht jedoch serializeWithType().

Die javadoc for this latter method sagt, dass diese Methode

genannt wird

[...] wenn zusätzliche Typinformationen werden voraussichtlich in der Serialisierung aufgenommen werden, für die Deserialisierung zu verwenden.

Ich verstehe einfach nicht, was das bedeutet ...

Wie kann ich eine Testumgebung einrichten, so dass diese Methode aufgerufen werden? Beachten Sie, dass der zu serialisierende JSON von einem beliebigen Typ sein kann, mit Ausnahme von Objekten (dh Boolean, Zahl, String, Array sind alle gültigen Typen).

Antwort

9

Diese Methode wird verwendet, wenn Sie Polymorphismus

public class A { 
    ... 
} 

public class B extends A { 
    ... 
} 

public class C extends A { 
    ... 
} 

verwenden möchten Wenn Sie eine Instanz von C serialisiert und dann versuchen, das resultierende json deserialisieren aber nur zu wissen, dass es ein Untertyp A:

Sie müssen etwas in dem resultierenden JSON speichern, um den realen Typ des serialisierten Objekts beizubehalten.

Dies kann entweder mit @JsonTypeInfo für Ihre Klasse oder durch den Aufruf enableDefaultTyping auf Ihrem ObjectMapper aktiviert werden.

Dies ist ein Beispiel Testfall mit JUnit & Mockito

import com.fasterxml.jackson.databind.JsonSerializable; 
import com.fasterxml.jackson.databind.ObjectMapper; 
import org.junit.Test; 

import static org.mockito.Matchers.any; 
import static org.mockito.Mockito.mock; 
import static org.mockito.Mockito.times; 
import static org.mockito.Mockito.verify; 

public class SerializeWithTypeTest { 

    private JsonSerializable serializable = mock(JsonSerializable.class); 

    @Test 
    public void shouldCallSerializeWithType() throws Exception { 
     final ObjectMapper objectMapper = new ObjectMapper().enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); 

     objectMapper.writeValueAsString(serializable); 

     // make sure serializeWithType is called once 
     verify(serializable, times(1)).serializeWithType(any(), any(), any()); 

    } 

} 
2

Versuchen Sie, JsonTypeInfo Annotation auf Ihre Klasse zu verwenden. Es sollte den Aufruf serializeWithType() auslösen. Es wird verwendet, um Informationen über den Typ zu speichern, der für polymorphe Typen erforderlich ist, oder um den abstrakten Typ und die passende konkrete Implementierung zu verknüpfen.

4

Jackson 2 is completely incompatible with Jackson 1 und JsonSerializableWithType (jetzt veraltet und unbrauchbar) ist eine Schnittstelle von Jackson 1, 2 auf die Anwesenheit von serializeWithType() in Jackson geführt.

serializeWithType() aufgerufen wird, wenn zusätzliche Typinformation erwartet wird, aufgenommen werden, was bedeutet, dass eine Anmerkung (JsonTypeInfo) ist die Angabe der Klasse property für Deserialisierung delega wenn Polymorphismus verwendet wird.Dieses Verfahren wird dann mit den zusätzlichen Typinformationen innerhalb eineine TypeSerializer genannt werden, die mit einem Typ-Präfix geschrieben werden können:

/* (.., .., TypeSerializer typeSer) */ { 
    typeSer.writeTypePrefixForScalar(.., .., ThisClass.class); 
}

Durch die Klasse mit @JsonTypeInfo mit Anmerkungen versehen, können Sie mit den Typinformationen angeben Serialisierung:

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, 
     include = As.WRAPPER_OBJECT, 
     property = "type") 
@JsonSubTypes({ 
     @Type(name = "typeint", value = MyInt.class), 
     @Type(name = "typefloat", value = MyFloat.class) 
}) 
public interface MyNumber {} 

@JsonTypeName("typeint") 
public MyInt implements MyNumber {} 

@JsonTypeName("typefloat") 
public MyFloat implements MyNumber {} 

Dann werden die Werte typeint und typefloat werden in der Eigenschaft mit dem Namen type eingestellt werden. Wenn Sie ein MyNumber deserialize, basiert es auf Polymorphismus. Thomas Maurel's answer demonstriert einen direkten Testansatz, indem das Objekt als String serialisiert und deseralisiert wird.