2015-02-07 8 views
7

Załóżmy serializacji do JSON zawiera nazwę klasy rzeczywistego obiektu, za pomocą tej adnotacji na klasę:Czy jackson może określić typ obiektu root, aby deserializować do, kiedy json zawiera właściwość type?

@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@type") 
class MyClass { 
    String foo; 
} 

Więc JSON jest na przykład:

{"@type": "com.example.MyClass", "foo": "bar"} 

Może to być rozszeregować bez określenia rodzaju ? I nie mam na myśli nawet supertypu. Po prostu coś takiego:

objectMapper.readValue(value, Object.class); 

co nie działa, przywraca mapę.

Odpowiedz

5

Cóż, na pewno można to zrobić, chociaż osobiście nigdy nie używałem tego w ten sposób. Możesz deserializować go do obiektu JsonNode, a następnie przekonwertować go do odpowiedniego typu.

final ObjectMapper objectMapper = new ObjectMapper(); 
final MyClass myClass = new MyClass(); 
myClass.foo = "bar"; 

// Serialize 
final String json = objectMapper.writeValueAsString(myClass); 

// Deserialize 
final JsonNode jsonNode = objectMapper.readTree(json); 

// Get the @type 
final String type = jsonNode.get("@type").asText(); 

// Create a Class-object 
final Class<?> cls = Class.forName(type); 

// And convert it 
final Object o = objectMapper.convertValue(jsonNode, cls); 

System.out.println(o.getClass()); 

Wyjście jest:

MojaKlasa

+2

O tak, myślę, że to działa. Zastanawiam się, czy nie było bardziej wbudowanego sposobu, ale myślę, że to nie miałoby sensu, ponieważ Jackson nie mógł wiedzieć, jak skonfigurowałem JsonTypeInfo, bez znajomości klasy. Wielkie dzięki. –

1

Tak, ale jest pewien wyjątek: Typ dasz musi być coś, który zawiera @JsonTypeInfo określić. Object.class nie będzie, chyba że użyjesz "adnotacji łączenia", aby je skojarzyć.

Jeśli jednak chcesz dodać informacje o typie właściwości (zadeklarowanego typu) java.lang.Object, prawdopodobnie chcesz włączyć domyślne pisanie: zobacz ObjectMapper.enableDefaultTyping(...), aby uzyskać więcej informacji. To rzeczywiście umożliwi włączenie (i użycie) informacji o typie dla większych kategorii klas, bez potrzeby dodawania adnotacji.

2
ObjectMapper mapper = new ObjectMapper(); 
    mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); 

    MyClass original = new MyClass(); 
    original.foo = "hello"; 

    String json = mapper.writeValueAsString(original); 
    MyClass foo = (MyClass) mapper.readValue(json, MyClass.class); 

To powinno działać i jest bardzo wygodne.

+0

Działa, jeśli wiesz, że JSON reprezentuje 'MyClass' w czasie deserializacji. Przyjąłem pytanie, aby odnieść się do scenariusza, w którym nie znasz typu obiektu. Taką sytuację próbuję sobie poradzić. –

+0

Jeśli nie znasz typu, możesz po prostu przypisać do obiektu. Object.getClass() powie ci, jaki to jest. – sydraz

Powiązane problemy