开发者

Java JSON Object Flattening

开发者 https://www.devze.com 2023-04-10 09:49 出处:网络
I am looking for a Java library to convert my domain objects into a flattened JSON eg. public class Person {

I am looking for a Java library to convert my domain objects into a flattened JSON

eg.

public class Person {
   String name
   Address homeAddress
}

public class Address {
  String street
  String zip
}

JSON: {name:'John', homeAddress_street: '123 Street', homeAddress_zip: 'xxxxx'}

I've looked into XStream, Eclipse MOXy, FlexJSON, JSON-lib & gson

My goal is to get rid of my json wrapper classes and minimize code. I would like to have a general service that would take any domain model class I have and get a json representation without having to write xml descriptors or any custom converters for each type of model. A depth of 1 level deep is sufficient for my models. I have not found an easy generic solution using annotations or built in functionality in the above libraries bu开发者_JAVA技巧t I have probably overlooked them. Is there a non intrusive library that can do this? or maybe one that I've listed? I'm using Hibernate so the library must be able to deal with CGLib Proxies


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

Below is an example of how this could be done with MOXy by leveraging the @XmlPath extension.

Person

package forum7652387;

import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlPath;

@XmlAccessorType(XmlAccessType.FIELD)
public class Person {
    String name;

    @XmlPath(".")
    Address homeAddress;
}

Address

package forum7652387;

import javax.xml.bind.annotation.*;

@XmlAccessorType(XmlAccessType.FIELD)
public class Address {
    @XmlElement(name="homeAddress_street")
    String street;

    @XmlElement(name="homeAddress_zip")
    String zip;
}

jaxb.properties

To specify MOXy as your JAXB provider you need to add a file called jaxb.properties in the same package as your domain classes with the following entry:

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

Demo

package forum7652387;

import java.io.StringReader;
import javax.xml.bind.*;
import javax.xml.transform.stream.StreamSource;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Person.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        unmarshaller.setProperty("eclipselink.media-type", "application/json");
        unmarshaller.setProperty("eclipselink.json.include-root", false);
        String jsonString = "{\"name\":\"John\", \"homeAddress_street\":\"123 Street\", \"homeAddress_zip\":\"xxxxx\"}";
        StreamSource jsonSource = new StreamSource(new StringReader(jsonString));
        Person person = unmarshaller.unmarshal(jsonSource, Person.class).getValue();

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty("eclipselink.media-type", "application/json");
        marshaller.setProperty("eclipselink.json.include-root", false);
        marshaller.marshal(person, System.out);
    }

}

Output

 {"name" : "John", "homeAddress_street" : "123 Street", "homeAddress_zip" : "xxxxx"}

For More Information

  • http://blog.bdoughan.com/2011/08/json-binding-with-eclipselink-moxy.html


I've used GSON very briefly and I think it does what you're looking for. While investigating it, I knocked up the following ludicrously simple example to confirm it was as simple as I needed; first, a POJO:

import java.util.List;

public class Member {

    private String name;
    private int age;
    private List<String> stuff;

    public Member() {
    }

    public String getName() {
        return name;
    }

    public void setName( String name ) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge( int age ) {
        this.age = age;
    }

    public List<String> getStuff() {
        return stuff;
    }

    public void setStuff( List<String> stuff ) {
        this.stuff = stuff;
    }

}

Then, the worker class:

import java.util.ArrayList;
import java.util.List;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class Main {

    public static void main( String[] args ) {
        Main m = new Main();
        m.execute( args );
    }

    private void execute( String[] args ) {
        Gson gson = new GsonBuilder().setPrettyPrinting().create();
        Member member = new Member();

        List<String> stuff = new ArrayList<String>();
        stuff.add( "shoes" );
        stuff.add( "hat" );
        member.setStuff( stuff );
        member.setName( "Bert" );
        member.setAge( 21 );

        String output = gson.toJson( member, Member.class );
        log( output );

        Member member2 = gson.fromJson( output, Member.class );
        log(member2.getName());
    }

    private void log( String text ) {
        System.out.println( text );
    }

}

No xml descriptors or custom converters needed. Is this the kind of thing you're after?

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号