Read embedded object in Jackson

前端 未结 3 1002
一整个雨季
一整个雨季 2020-12-14 08:27

I\'m trying to read a legacy JSON code using Jackson 2.0-RC3, however I\'m stuck with an \"embedded\" object.

Given a following JSON:

{
    \"title\"         


        
相关标签:
3条回答
  • 2020-12-14 09:02

    Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB 2 (JSR-222) expert group.

    I'm not sure if Jackson supports this use case, but below is an example of how you can leverage MOXy's @XmlPath extension to meet your requirements. Note you will need to use an EclipseLink 2.4.0 nightly label from April 7, 2012 or newer.

    • http://www.eclipse.org/eclipselink/downloads/nightly.php

    Item

    The author property on Item is mapped with @XmlPath('.'). This means that the content of Author is pulled up to the same level as the content for Item. I also needed to use an XmlAdapter for the Date property as the format you are using doesn't match MOXy's default representation.

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

    Author

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

    A file called jaxb.properties with the following entry must be placed in the same package as the domain classes to specify MOXy as the JAXB (JSR-222) provider.

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

    For More Information

    • http://blog.bdoughan.com/2010/07/xpath-based-mapping.html
    • http://blog.bdoughan.com/2011/08/json-binding-with-eclipselink-moxy.html
    • http://blog.bdoughan.com/2011/08/binding-to-json-xml-geocode-example.html
    0 讨论(0)
  • 2020-12-14 09:22

    I would deserialize the original JSON to a single, flat object first (kind of like an adapter), then create your own domain objects.

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

    Then use this object to fill out your Item and Author objects and create the correct relationships.

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

    Your Item class could only be automatically deserialized from the following form:

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

    You might be able to do something with custom deserialization, but it would not be the simpler solution for sure.

    0 讨论(0)
  • 2020-12-14 09:23

    To deal with an "embedded" object you should use @JsonUnwrapped — it's an equivalent of the Hibernate's @Embeddable/@Embedded.

    class Item {
        private String title;
    
        @JsonProperty("date")
        private Date createdAt;
    
        // How to map this?
        @JsonUnwrapped
        private Author author;
    }
    
    0 讨论(0)
提交回复
热议问题