moxy json介绍
GlassFish 4现在可以提供完整的Java EE 7(JSR-342)平台。 EclipseLink为该发行版做出了一些重大贡献。 首先是提供JPA 2.1(JSR-338)实现。 我将在本文中介绍的第二个内容是EclipseLink MOXy,它现在是JAX-RS应用程序的默认JSON绑定提供程序。
RESTful服务
客户服务
通常,JPA将支持真实的服务来执行持久性操作(请参阅: 创建RESTful Web服务–第4/5部分 )。 但是对于这篇文章,我将使用“ Hello World”
样式服务,该服务基于ID作为XML和JSON返回一个Customer ,以说明有关绑定的一些要点。
package org.example.service;
import javax.ejb.*;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import org.example.model.*;
@Stateless
@LocalBean
@Path("/customers")
public class CustomerService {
@GET
@Produces({
MediaType.APPLICATION_XML,
MediaType.APPLICATION_JSON
})
@Path("{id}")
public Customer read(@PathParam("id") int id) {
Customer customer = new Customer();
customer.setId(id);
customer.setName("Jane Doe");
PhoneNumber pn = new PhoneNumber();
pn.setType("work");
pn.setValue("5551111");
customer.getPhoneNumbers().add(pn);
return customer;
}
}
客户申请
我使用了Application类来指定服务的路径。
package org.example.service;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
@ApplicationPath("rest/*")
public class CustomerApplication extends Application {
}
Java模型
以下是我们用于此示例的Java模型。 目标是使用一组元数据生成良好的XML和JSON表示形式。
顾客
关于Customer类,有几点有趣的事情要注意。
- id属性是一个int 。 由于JSON具有不同的数字和文本表示方式,因此我们将研究如何在JSON输出中表示该值。
- phoneNumbers属性的类型为List <PhoneNumber> 。 已使用@XmlElementWrapper对其进行注释,以产生良好的XML输出。 我们将研究这样做对JSON输出的影响。
package org.example.model;
import java.util.*;
import javax.xml.bind.annotation.*;
@XmlRootElement
public class Customer {
private int id;
private String name;
private List<PhoneNumber> phoneNumbers = new ArrayList<PhoneNumber>();
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@XmlElementWrapper
@XmlElement(name="phoneNumber")
public List<PhoneNumber> getPhoneNumbers() {
return phoneNumbers;
}
}
电话号码
在XML中, PhoneNumber类映射到具有简单内容的复杂类型(请参阅: JAXB和具有简单内容的复杂类型 )。 这意味着它将映射到具有属性和文本的XML元素。 这些XML概念并不直接与JSON概念相对应,因此我们将研究JSON表示形式。
package org.example.model;
import javax.xml.bind.annotation.*;
public class PhoneNumber {
private String type;
private String value;
@XmlAttribute
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
@XmlValue
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
使用服务
要求– GET
以下是我们用于访问服务的URL:
http://localhost:8080/CustomerResource/rest/customers/1
响应(应用程序/ xml)
由于我们将域模型映射为
JAXB(JSR-222)元数据下面的XML表示并不奇怪。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<customer id="1">
<name>Jane Doe</name>
<phoneNumbers>
<phoneNumber type="work">5551111</phoneNumber>
</phoneNumbers>
</customer>
响应(应用程序/ json)– GlassFish 3.1.2
让我们看看在MOXy是默认的JSON绑定提供程序之前,GlassFish 3.1.2中的JSON表示是什么样的。 有几件事要注意:
- id属性的int值表示为JSON文本。
- 类型为List <PhoneNumber>的phoneNumbers属性
因为它只有一个项目被表示为JSON对象而不是JSON数组。 同样,即使此键包含一个集合,它仍称为phoneNumber 。 - 自类型属性使用@XmlAttribute注释以来,与type属性相对应的JSON关键字以@ 开头 。
- 自从使用@XmlValue进行注释以来,与value属性对应的JSON密钥称为$ 。
{
"id": "1",
"name": "Jane Doe",
"phoneNumbers": {
"phoneNumber": {
"@type": "work",
"$": "5551111"
}
}
}
响应(应用程序/ json)– GlassFish 4
使用默认配置,您将看到升级到GlassFish 4消除了两个最大的问题:
- 数值–现在, id属性已作为数字值正确编组到JSON。 这不是技巧,MOXy将JSON表示形式基于属性的Java类型。 PhoneNumber实例上的String类型的value属性仅包含数字,并且已作为文本正确编组到JSON。
- 大小为1的集合–现在, phoneNumber键是一个JSON数组,不幸的是,它仍称为phoneNumber (我将在下一步演示如何解决此问题)。
{
"id": 1,
"name": "Jane Doe",
"phoneNumbers": {
"phoneNumber": [
"@type": "work",
"$": "5551111"
]
}
}
自定义JSON绑定
现在可以通过利用JAX-RS ContextResolver机制来配置MOXy。 您只需要返回MOXyJsonConfig的实例。 我们将使用它来执行以下操作:
- 指定我们不想为与@XmlAttribute映射的属性相对应的JSON关键字添加前缀。
- 使用JSON关键值 ,而不是$与@XmlValue映射属性。
- MOXyJsonConfig也可以用于将属性向下传递给Marshaller / Unmarshaller。 我们将执行此操作以清理集合属性的JSON密钥(请参阅: 绑定到JSON&XML –处理集合 )。
package org.example.service;
import javax.ws.rs.ext.*;
import org.eclipse.persistence.jaxb.JAXBContextProperties;
import org.glassfish.jersey.moxy.json.MoxyJsonConfig;
@Provider
public class MOXyJsonContextResolver implements ContextResolver<MoxyJsonConfig> {
private final MoxyJsonConfig config;
public MOXyJsonContextResolver() {
config = new MoxyJsonConfig()
.setAttributePrefix("")
.setValueWrapper("value")
.property(JAXBContextProperties.JSON_WRAPPER_AS_ARRAY_NAME, true);
}
@Override
public MoxyJsonConfig getContext(Class<?> objectType) {
return config;
}
}
新回应
最后,我们有一个我们可以满意的JSON表示形式。 它不包含任何与XML相关的工件,即使它是使用与XML表示相同的元数据生成的(未更改)。 只需要一点点MOXy。
{
"id": 1,
"name": "Jane Doe",
"phoneNumbers": [
{
"type": "work",
"value": "5551111"
}
]
}
moxy json介绍