最新的jave ee 7中,对JSON的解析实现使用的是JSR-353,其中,Eclipse旗下的EclipseLink开源项目向JAVE EE 7中贡献了不少力量,其中包括JPA 2.1 (JSR-338)的实现,另外一个贡献是本文向大家介绍的EclipseLink MOXy项目,它是JAVE EE 7中JAX-RS(REST标准)的一个默认的JSON Provider.
首先简单介绍下Eclipse旗下的EclipseLink开源项目,它主要用来实现快速将JAVA中的对象转化为各种类型的XML,该项目主要有如下的特性:
支持JAXB中最多的注解
同时支持XML和JSON
支持最新的JPA 2.1
对JPA-RS的增强支持
MOXY有十分强大的将各类JAVA对象 序列化为XML以及XML反序列化为JAVA对象的能力。这在REST架构的应用中,MOXY可以用来实现JAX-RS标准中的各种转换,
下面选用一个例子大致讲解下,首先是一个jaxb声明的pojo,如下
@XmlType(propOrder={"id", "firstName", "lastName", "phoneNumbers"}) public class Customer { private int id; private String firstName; private String lastName; private List<PhoneNumber> phoneNumbers = new ArrayList<PhoneNumber>(); public int getId() { return id; } public void setId(int id) { this.id = id; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } @XmlElement(nillable=true) public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } @XmlElement public List<PhoneNumber> getPhoneNumbers() { return phoneNumbers; } }
PhoneNumber类如下:
import javax.xml.bind.annotation.*; @XmlAccessorType(XmlAccessType.FIELD) public class PhoneNumber { private String type; private String number; public String getType() { return type; } public void setType(String type) { this.type = type; } public String getNumber() { return number; } public void setNumber(String number) { this.number = number; } }
要使用moxy的话,要在model的相同目录下,放置jaxb.properties 文件,内容为:
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
下面来看下如何对对象进行序列化为JSON,使用的是MOXy的 JsonObjectBuilderResult和JsonArrayBuilderResult.
import java.util.*; import javax.json.*; import javax.json.stream.JsonGenerator; import javax.xml.bind.*; import org.eclipse.persistence.jaxb.JAXBContextProperties; import org.eclipse.persistence.oxm.json.*; public class MarshalDemo { public static void main(String[] args) throws Exception { Map<String, Object> jaxbProperties = new HashMap<String, Object>(2); jaxbProperties.put(JAXBContextProperties.MEDIA_TYPE, "application/json"); jaxbProperties.put(JAXBContextProperties.JSON_INCLUDE_ROOT, false); JAXBContext jc = JAXBContext.newInstance(new Class[] {Customer.class}, jaxbProperties); Marshaller marshaller = jc.createMarshaller(); //创建 JsonArrayBuilder JsonArrayBuilder customersArrayBuilder = Json.createArrayBuilder(); Customer customer = new Customer(); customer.setId(1); customer.setFirstName("Jane"); customer.setLastName(null); PhoneNumber phoneNumber = new PhoneNumber(); phoneNumber.setType("cell"); phoneNumber.setNumber("555-1111"); customer.getPhoneNumbers().add(phoneNumber); JsonArrayBuilderResult result = new JsonArrayBuilderResult(customersArrayBuilder); marshaller.marshal(customer, result); List<PhoneNumber> phoneNumbers = new ArrayList<PhoneNumber>(2); PhoneNumber workPhone = new PhoneNumber(); workPhone.setType("work"); workPhone.setNumber("555-2222"); phoneNumbers.add(workPhone); PhoneNumber homePhone = new PhoneNumber(); homePhone.setType("home"); homePhone.setNumber("555-3333"); phoneNumbers.add(homePhone); JsonArrayBuilderResult arrayBuilderResult = new JsonArrayBuilderResult(); marshaller.marshal(phoneNumbers, arrayBuilderResult); customersArrayBuilder // 用JSR-353 APIs 额外添加数据 .add(Json.createObjectBuilder() .add("id", 2) .add("firstName", "Bob") .addNull("lastName") // Included Marshalled PhoneNumber Objects .add("phoneNumbers", arrayBuilderResult.getJsonArrayBuilder()) ) .build(); // Write JSON to System.out Map<String, Object> jsonProperties = new HashMap<String, Object>(1); jsonProperties.put(JsonGenerator.PRETTY_PRINTING, true); JsonWriterFactory writerFactory = Json.createWriterFactory(jsonProperties); JsonWriter writer = writerFactory.createWriter(System.out); writer.writeArray(customersArrayBuilder.build()); writer.close(); } }
输出为:
[
{
"id":1,
"firstName":"Jane",
"lastName":null,
"phoneNumbers":[
{
"type":"cell",
"number":"555-1111"
}
]
},
{
"id":2,
"firstName":"Bob",
"lastName":null,
"phoneNumbers":[
{
"type":"work",
"number":"555-2222"
},
{
"type":"home",
"number":"555-3333"
}
]
}
]
然后来一个反序列化的例子:
import java.io.FileInputStream; import java.util.*; import javax.json.*; import javax.xml.bind.*; import org.eclipse.persistence.jaxb.JAXBContextProperties; import org.eclipse.persistence.oxm.json.JsonStructureSource; public class UnmarshalDemo { public static void main(String[] args) throws Exception { try (FileInputStream is = new FileInputStream("src/blog/jsonp/moxy/input.json")) { Map<String, Object> jaxbProperties = new HashMap<String, Object>(2); jaxbProperties.put(JAXBContextProperties.MEDIA_TYPE, "application/json"); jaxbProperties.put(JAXBContextProperties.JSON_INCLUDE_ROOT, false); JAXBContext jc = JAXBContext.newInstance(new Class[] {Customer.class}, jaxbProperties); Unmarshaller unmarshaller = jc.createUnmarshaller(); // Parse the JSON JsonReader jsonReader = Json.createReader(is); // Unmarshal Root Level JsonArray JsonArray customersArray = jsonReader.readArray(); JsonStructureSource arraySource = new JsonStructureSource(customersArray); List<Customer> customers = (List<Customer>) unmarshaller.unmarshal(arraySource, Customer.class) .getValue(); for(Customer customer : customers) { System.out.println(customer.getFirstName()); } // Unmarshal Nested JsonObject JsonObject customerObject = customersArray.getJsonObject(1); JsonStructureSource objectSource = new JsonStructureSource(customerObject); Customer customer = unmarshaller.unmarshal(objectSource, Customer.class) .getValue(); for(PhoneNumber phoneNumber : customer.getPhoneNumbers()) { System.out.println(phoneNumber.getNumber()); } } } }
输入的JSON:
[
{
"id":1,
"firstName":"Jane",
"lastName":null,
"phoneNumbers":[
{
"type":"cell",
"number":"555-1111"
}
]
},
{
"id":2,
"firstName":"Bob",
"lastName":null,
"phoneNumbers":[
{
"type":"work",
"number":"555-2222"
},
{
"type":"home",
"number":"555-3333"
}
]
}
]
输出结果:
Jane
2 Bob
3 555-2222
4 555-3333
同时可以参考偶的译文:
http://developer.51cto.com/art/201306/399778.htm