杰克逊 - 仅在列表属性中的对象的ID序列化



我想优化要在电线上发送的JSON数据。我的代码中有三个模型。这些是客户,发票,特别是。

客户类

@Data
public class Customer implements Serializable {
    private long customerId;
    private String name;
    private String taxId;
    private String phone;
    private String address;
    private String emailId;
    private Date created;
    private List<Invoice> invoices;
}

发票类

@Data
public class Invoice implements Serializable {
    private String invoiceId;
    private List<Particular> particulars;
    private Date invoiceDate;
}

特定类

@Data
public class Particular {
    private String item;
    private int quantity;
    private float tax;
    private int unitPrice;
}

我的测试代码:

@Test
    public void makeCustomerJsonWithInvoices() throws JsonProcessingException {
        Customer customer = new Customer();
        customer.setCustomerId(1234);
        customer.setName("Pawan");
        customer.setPhone("+918989898989");
        customer.setEmailId("something@something.com");
        customer.setAddress("Mumbai, India");
        customer.setTaxId("MQZ11DPS");
        customer.setCreated(new Date());
        Invoice invoice1 = new Invoice();
        invoice1.setInvoiceId("A-1");
        Particular particular1 = new Particular("abc", 1, 0, 12);
        Particular particular2 = new Particular("xyz", 2, 0, 20);
        invoice1.setInvoiceDate(new Date());
        invoice1.setParticulars(Arrays.asList(particular1, particular2));
        Particular particular3 = new Particular("mno", 2, 0, 15);
        Invoice invoice2 = new Invoice();
        invoice2.setInvoiceId("A-2");
        invoice2.setParticulars(Arrays.asList(particular3));
        invoice2.setInvoiceDate(new Date());
        customer.setInvoices(Arrays.asList(invoice1, invoice2));
        String value = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(customer);
        System.out.println(value);
    }

我想要的是通过序列化发票来避免冗余,以使所得的JSON紧凑。这应该仅通过发送invoiceId属性值而不是整个发票对象JSON来实现。

测试代码打印的内容:

{
  "customerId" : 1234,
  "name" : "Pawan",
  "taxId" : "MQZ11DPS",
  "phone" : "+918989898989",
  "address" : "Mumbai, India",
  "emailId" : "something@something.com",
  "created" : 1553243962038,
  "invoices" : [ {
    "invoiceId" : "A-1",
    "particulars" : [ {
      "item" : "abc",
      "quantity" : 1,
      "tax" : 0.0,
      "unitPrice" : 12
    }, {
      "item" : "xyz",
      "quantity" : 2,
      "tax" : 0.0,
      "unitPrice" : 20
    } ],
    "invoiceDate" : 1553243962038
  }, {
    "invoiceId" : "A-2",
    "particulars" : [ {
      "item" : "mno",
      "quantity" : 2,
      "tax" : 0.0,
      "unitPrice" : 15
    } ],
    "invoiceDate" : 1553243962039
  } ]
}

我想要它打印的内容:

{
  "customerId" : 1234,
  "name" : "Pawan",
  "taxId" : "MQZ11DPS",
  "phone" : "+918989898989",
  "address" : "Mumbai, India",
  "emailId" : "something@something.com",
  "created" : 1553243962038,
  "invoices" : [ {
    "invoiceId" : "A-1"
  }, {
    "invoiceId" : "A-2"
  } ]
}

@Data是Lombok注释,用于生成Getters和Setter。

我尝试将@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "invoiceId")注释添加到发票类中,但这不会改变输出。

请注意,我希望只有在小时候将其传递给容器模型时才会发生这种序列化。如果我想独立发送发票,则将在发票模型中序列化所有字段。我相信这是实施静止WS的常见情况。

我需要为此编写客户序列化器吗?

我能够通过以下方式修改客户类来实现这一目标。

@Data
public class Customer implements Serializable {
    private long customerId;
    private String name;
    private String taxId;
    private String phone;
    private String address;
    private String emailId;
    private Date created;
    @JsonIdentityInfo(generator= ObjectIdGenerators.PropertyGenerator.class, property="invoiceId")
    @JsonIdentityReference(alwaysAsId=true)
    private List<Invoice> invoices;
}

答案灵感来自https://stackoverflow.com/a/17583175/1365340

使用此功能,我可以使用发票ID列表生成Customer JSON。Invoice序列化分别从JSON中从其所有字段中获取所有值。

您可以使用@JsonIgnore在JSON响应中插入属性。

或者您可以使用transient关键字避免序列化

将以下bean视为对案例的轻微修改:

@Data
@JsonFilter("idOnlyFilter")
@AllArgsConstructor
class Complex {
    private String id;
    private List<String> aList;
    private Date aDate;
}

您可以使用@JsonFilter概念来定义您想要的每个豆子,序列化条件是什么。特别注意ObjectMapper配置以及@JsonFilter注释中的过滤器名称 idOnlyFilter

这起作用如下所示:

@Test
public void includeOnlyOneField() throws JsonProcessingException {
    ObjectMapper mapper = new ObjectMapper();
    FilterProvider filters = new SimpleFilterProvider()
            .addFilter("idOnlyFilter", SimpleBeanPropertyFilter.filterOutAllExcept("id"));
    Complex complex = new Complex("a string", List.of(), new Date());
    // when
    String complexAsString = mapper.writer(filters).writeValueAsString(complex);
    // then
    assertThat(complexAsString).isEqualTo("{"id":"a string"}");
}

您可以在Invoice类上使用@JsonAutoDetect仅序列化invoiceId字段,例如:

@JsonAutoDetect(
    fieldVisibility = Visibility.NONE,
    setterVisibility = Visibility.NONE,
    getterVisibility = Visibility.NONE,
    isGetterVisibility = Visibility.NONE,
    creatorVisibility = Visibility.NONE
)
@Data
public class Invoice implements Serializable {
    @JsonProperty (access = READ_ONLY)
    private String invoiceId;
    private List<Particular> particulars;
    private Date invoiceDate;
}

这将确保仅invoiceId通过电线,在此处查看文档。

update

如果仅在将Invoice作为嵌套对象发送时才能具有此行为,则可以将其他字段设置为null(或者首先不设置这些字段)并使用@JsonInclude注释,例如:

@JsonInclude(Include.NON_NULL)
@Data
public class Invoice implements Serializable {
  ..
}

最新更新