如何配置球衣客户端使用服务器期望的相同 json 格式?

How do I configure the jersey client to use the same json format that the server expects?

这是我需要的 json(由 Ember 生成,但在服务器上有效):

{"customer":{"partyType":"jdo.party.model.Organization","name":"asdf"}}

这是 json 我得到的:

{"id":null,"partyType":"jdo.party.model.Company","name":"Test Company","firstName":"","lastName":""}

我需要球衣客户端发出正确的 json,我不确定为什么。 客户代码:

client = ClientBuilder.newClient();
client.register(JacksonFeature.class);
client.register(new LoggingFilter(Logger.getGlobal(),true));
resource = client.target("http://localhost:8090/crm/api").path("/customers");
CustomerDto dto = new CustomerDto(null, "jdo.party.model." + type, name, "", "");
response = resource.request()
                .accept(APPLICATION_JSON)
                .post(Entity.json(dto), CustomerDto.class);

我正在将客户端和服务器上的 class 转换为 json:

@XmlAccessorType(XmlAccessType.NONE)
@XmlRootElement(name = "customer")
@JsonRootName("customer")
public class CustomerDto implements Serializable {

    @XmlAttribute
    private UUID id;
    @XmlAttribute
    @NotEmpty
    private String partyType;
    @XmlAttribute
    private String name;
    @XmlAttribute
    private String firstName;
    @XmlAttribute
    private String lastName;

    public CustomerDto(Party party) {
        if (party instanceof Person) {
            partyType = ((Person) party).getClass().getCanonicalName();
            firstName = ((Person) party).getFirstName();
            lastName = ((Person) party).getLastName();
        } else if (party instanceof Organization) {
            partyType = ((Organization) party).getClass().getCanonicalName();
            name = ((Organization) party).getName();
        } else {
            throw new IllegalArgumentException(
                    String.format("Customer must be person or Organization.  %s was passed instead.",
                            party.getClass().getCanonicalName()));
        }
        id = party.getId();
    }

    @AssertTrue
    public boolean hasName() {
        return isNotBlank(name) || isNotBlank(lastName);
    }

    public String getPartyType() {
        return partyType;
    }

    public String getName() {
        return name;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((firstName == null) ? 0 : firstName.hashCode());
        result = prime * result + ((id == null) ? 0 : id.hashCode());
        result = prime * result + ((lastName == null) ? 0 : lastName.hashCode());
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        result = prime * result + ((partyType == null) ? 0 : partyType.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        CustomerDto other = (CustomerDto) obj;
        if (firstName == null) {
            if (other.firstName != null)
                return false;
        } else if (!firstName.equals(other.firstName))
            return false;
        if (id == null) {
            if (other.id != null)
                return false;
        } else if (!id.equals(other.id))
            return false;
        if (lastName == null) {
            if (other.lastName != null)
                return false;
        } else if (!lastName.equals(other.lastName))
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        if (partyType == null) {
            if (other.partyType != null)
                return false;
        } else if (!partyType.equals(other.partyType))
            return false;
        return true;
    }

    @Override
    public String toString() {
        return "CustomerDto [id=" + id + ", partyType=" + partyType + ", name=" + name + ", firstName=" + firstName
                + ", lastName=" + lastName + "]";
    }

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public UUID getId() {
        return id;
    }

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    public CustomerDto() {
        super();
    }

    public CustomerDto(UUID id, String partyType, String name, String firstName, String lastName) {
        super();
        this.id = id;
        this.partyType = partyType;
        this.name = name;
        this.firstName = firstName;
        this.lastName = lastName;
    }

}

所以我们需要完成两件事:

  1. 忽略 DTO 中的空值
  2. 将 JSON 对象包装在根值中。

1。忽略空值

你可以...

最简单的方法是用

注释 DTO
@JsonInclude(JsonInclude.Include.NON_NULL)

这将告诉 Jackson 忽略空值。您还需要确保传递 null 作为构造函数值而不是 "" (这不是一回事)。

你可以...

如果你想全局设置这个属性,你可以在ObjectMapper

上配置它
ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

我们可以通过多种方式注册此 ObjectMapper 以在我们的应用程序中使用

  1. ContextResolver 中配置它,如 所示。然后用客户端注册ContextResolver

    client.register(new ObjectMapperContextResolver());
    
  2. 使用 Jackson 提供程序实例配置映射器

    client.register(new JacksonJaxbJsonProvider(objectMapper, null));
    

2。换行 JSON

我只知道一种方法,那就是配置 ObjectMapper

ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.WRAP_ROOT_VALUE, true);

实际使用的值由您的@JsonRootName注释值决定。

有关配置映射器以与应用程序一起使用的方法,请参见上文。


注意,要保持对 Jaxb 注释的支持,您可能需要使用 ObjectMapper

注册
mapper.registerModule(new JaxbAnnotationModule());

这个我不确定,因为使用 JacksonFeature,JAXB 注释已经被支持。但我不知道提供 ObjectMapper 是否会覆盖它。与显式使用 JacksonJaxbJsonProvider 相同。所以你可能只是想测试一下。

如果您只需要 JSON 中的 partyType 和 name 属性,那么为什么要在 CustomerDto.java class

中注释其他字段