2012-04-05 2 views
9

Sto provando a leggere un codice JSON legacy usando Jackson 2.0-RC3, tuttavia sono bloccato con un oggetto "incorporato".Leggi oggetto incorporato in Jackson

dato un seguito JSON:

{ 
    "title": "Hello world!", 
    "date": "2012-02-02 12:23:34". 
    "author": "username", 
    "author_avatar": "http://.../", 
    "author_group": 123, 
    "author_prop": "value" 
} 

Come posso mappare nella seguente struttura:

class Author { 
    @JsonPropery("author") 
    private String name; 

    @JsonPropery("author_avatar") 
    private URL avatar; 

    @JsonProperty("author_group") 
    private Integer group; 

    ... 
} 

class Item { 
    private String title; 

    @JsonProperty("date") 
    private Date createdAt; 

    // How to map this? 
    private Author author; 
} 

stavo cercando di farlo con @JsonDeserialize ma sembra che avrei dovuto mappare l'intero oggetto Item in questo modo.

risposta

24

di affrontare un oggetto "embedded" si dovrebbe usare @JsonUnwrapped - è un equivalente del Hibernate @Embeddable/@Embedded.

class Item { 
    private String title; 

    @JsonProperty("date") 
    private Date createdAt; 

    // How to map this? 
    @JsonUnwrapped 
    private Author author; 
} 
1

Vorrei deserializzare il JSON originale in un oggetto singolo, piatto (come un adattatore), quindi creare i propri oggetti di dominio.

class ItemLegacy { 
    private String title; 

    @JsonProperty("date") 
    private Date createdAt; 

    @JsonPropery("author") 
    private String name; 

    @JsonPropery("author_avatar") 
    private URL avatar; 

    @JsonProperty("author_group") 
    private Integer group; 

    @JsonProperty("author_prop") 
    private Integer group; 
} 

Quindi utilizzare questo oggetto per compilare gli oggetti Oggetto e Autore e creare le relazioni corrette.

//... the deserialized original JSON 
ItemLegacy legacy ... 

// create an author 
Author author = new Author(); 
author.setName(legacy.getName()); 
author.setGroup(legacy.getGroup()); 
... 

// create an item 
Item item = new Item(); 
item.setTitle(legacy.getTitle()); 
... 

// finally set the author... and you should have the desired structure 
item.setAuthor(author); 

tuoItem classe potrebbe essere deserializzato automaticamente solo dal il seguente modulo:

{ 
    "title": "Hello world!", 
    "date": "2012-02-02 12:23:34". 
    "author": { 
       "name": "username", 
       "author_avatar": "http://...", 
       "author_group": "123", 
       "author_prop": "value" 
       } 
} 

potrebbe essere in grado di fare qualcosa con la deserializzazione personalizzato, ma non sarebbe la soluzione più semplice di sicuro.

+0

Non è necessario serializzare sul JSON corretto. Tutto ciò di cui ho bisogno è ** deserializzare ** da JSON legacy in oggetti ben formati. – Crozin

+0

Spero che le mie modifiche chiariscano che non stavo parlando di serializzazione ... –

+0

Oh, ora capisco. Speravo che Jackson fornisse un equivalente di '@ Embeddable' /' Embedded 'di Hibernate. – Crozin

0

Nota: Sono in vantaggio EclipseLink JAXB (MOXy) e un membro del gruppo di esperti JAXB 2 (JSR-222).

Non sono sicuro che Jackson supporti questo caso d'uso, ma di seguito è riportato un esempio di come sfruttare l'estensione @XmlPath di MOXy per soddisfare i requisiti. Nota che dovrai utilizzare un'etichetta nightly EclipseLink 2.4.0 dal 7 aprile 2012 o più recente.

Articolo

La proprietà author su Item è mappato con @XmlPath('.'). Ciò significa che il contenuto di Author viene visualizzato allo stesso livello del contenuto di Item. Inoltre, dovevo utilizzare un XmlAdapter per la proprietà Date poiché il formato che stai utilizzando non corrisponde alla rappresentazione predefinita di MOXy.

package forum10036530; 

import java.util.Date; 
import javax.xml.bind.annotation.*; 
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; 
import org.eclipse.persistence.oxm.annotations.XmlPath; 

@XmlAccessorType(XmlAccessType.FIELD) 
class Item { 
    private String title; 

    @XmlElement(name="date") 
    @XmlJavaTypeAdapter(DateAdapter.class) 
    private Date createdAt; 

    @XmlPath(".") 
    private Author author; 
} 

Autore

package forum10036530; 

import java.net.URL; 
import javax.xml.bind.annotation.*; 

@XmlAccessorType(XmlAccessType.FIELD) 
class Author { 
    @XmlElement(name="author") 
    private String name; 

    @XmlElement(name="author_avatar") 
    private URL avatar; 

    @XmlElement(name="author_group") 
    private Integer group; 

    @XmlElement(name="author_prop") 
    private String prop; 
} 

DateAdapter

package forum10036530; 

import java.text.SimpleDateFormat; 
import java.util.Date; 
import javax.xml.bind.annotation.adapters.XmlAdapter; 

public class DateAdapter extends XmlAdapter<String, Date> { 

    private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); 

    @Override 
    public Date unmarshal(String string) throws Exception { 
     return dateFormat.parse(string); 
    } 

    @Override 
    public String marshal(Date date) throws Exception { 
     return dateFormat.format(date); 
    } 

} 

JAXB.Proprietà

Un file denominato jaxb.properties con la seguente voce deve essere inserito nello stesso pacchetto delle classi di dominio per specificare MOXy come provider JAXB (JSR-222).

javax.xml.bind.context.factory = org.eclipse.persistence.jaxb.JAXBContextFactory 

input.json/Output

{ 
    "title" : "Hello world!", 
    "date" : "2012-02-02 12:23:34", 
    "author" : "username", 
    "author_avatar" : "http://www.example.com/foo.png", 
    "author_group" : 123, 
    "author_prop" : "value" 
} 

Per ulteriori informazioni

+1

Non l'ho ancora provato, ma questo è esattamente quello che stavo cercando. – Crozin

+0

@Crozin - Ho dovuto inserire una correzione per gestire la proprietà URL in modo che l'esempio completo richieda la generazione di stasera, ma tutto il resto funziona con la build corrente. –