2012-04-05 19 views
9

Estoy tratando de leer un código JSON heredado usando Jackson 2.0-RC3, sin embargo, estoy atascado con un objeto "incrustado".Leer objeto incrustado en Jackson

dado un JSON siguiente:

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

¿Cómo se puede mapear I en la siguiente estructura:

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

yo estaba tratando de hacer eso con @JsonDeserialize pero parece que tendría que mapee todo el objeto Item de esa manera.

Respuesta

24

Para hacer frente a un objeto "incrustado" se debe utilizar @JsonUnwrapped - es un equivalente de la hibernación @Embeddable/@Embedded.

class Item { 
    private String title; 

    @JsonProperty("date") 
    private Date createdAt; 

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

Deserializaría el JSON original en primer lugar, un objeto plano (como un adaptador) y luego crearía sus propios objetos de 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; 
} 

A continuación, utilice este objeto para completar sus objetos Artículo y Autor y cree las relaciones correctas.

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

SuItem clase sólo podía deserialized automáticamente de la siguiente forma:

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

Usted puede ser capaz de hacer algo con deserialización costumbre, pero no sería la solución más simple sin lugar a duda.

+0

No necesito serializar al JSON correcto. Todo lo que necesito es ** deserializar ** de JSON heredado en objetos bien formados. – Crozin

+0

Espero que mis ediciones aclaren que no estaba hablando de serialización ... –

+0

Oh, ahora lo entiendo. Esperaba que Jackson proporcionara un equivalente de '@ Embeddable' /' @ Embedded' de Hibernate. – Crozin

0

Nota: Soy el EclipseLink JAXB (MOXy) de plomo y un miembro del grupo de expertos JAXB 2 (JSR-222).

No estoy seguro de si Jackson admite este caso de uso, pero a continuación se muestra un ejemplo de cómo puede aprovechar la extensión @XmlPath de MOXy para cumplir con sus requisitos. Tenga en cuenta que deberá utilizar una etiqueta EclipseLink 2.4.0 nightly desde el 7 de abril de 2012 o posterior.

artículo

La propiedad author en Item es correlacionado con @XmlPath('.'). Esto significa que el contenido de Author se tira al mismo nivel que el contenido de Item. También necesitaba usar un XmlAdapter para la propiedad Date ya que el formato que está utilizando no coincide con la representación predeterminada de 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; 
} 

Autor

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.propiedades

Se debe colocar un archivo llamado jaxb.properties con la siguiente entrada en el mismo paquete que las clases de dominio para especificar MOXy como el proveedor JAXB (JSR-222).

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

input.json/salida

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

Para más información

+1

No lo he probado todavía, pero esto es exactamente lo que estaba buscando. – Crozin

+0

@Crozin - Tuve que poner una solución para manejar la propiedad URL así que el ejemplo completo requerirá la creación de tonights, pero todo lo demás funciona con la compilación actual. –

Cuestiones relacionadas