当前位置: 首页 > 知识库问答 >
问题:

Jackson-仅序列化JavaPojo列表属性中的对象ID

燕嘉熙
2023-03-14

我想优化要在线发送的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属性值而不是整个Invoice对象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"
  } ]
}

数据是用于生成getter和setter的lombok注释。

我试图添加@JsonIdtyInfo(生成器=ObjectIdGenerators。属性Generator.class,属性="发票ID")注释到发票类,但这不会改变输出。

请注意,我希望只有当发票作为子对象传递给容器模型时,才会使用发票进行序列化。如果我想独立发送发票,它应该序列化发票模型中的所有字段。我相信这是实现RESTful WS时常见的场景。

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

共有3个答案

孙德本
2023-03-14

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

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

您可以使用@JsonFilter概念在您想要的每个bean上定义真正精细的序列化条件。特别注意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\"}");
}
微生永春
2023-03-14

您可以在JSON响应中使用ingnoring属性。

或者您可以使用瞬态关键字来避免序列化

廉子民
2023-03-14

我可以通过以下方式修改Customer类来实现这一点。

@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列表的json。单独序列化时,Invoice对象从json中的所有字段获取所有值。

 类似资料:
  • 我有一个抽象的超类A,我有几个具体的子类B,C,D 在序列化方面,我执行以下操作: 没问题。我现在想反序列化这个。我知道我不能实例化一个抽象类,那么这是如何实现的呢? 这不起作用: 编辑:我把这个添加到我的抽象超类中:(仍然没有运气) 再次编辑:我现在遇到以下错误: 看看JSON,@class不在那里。我怎样才能做到?我试过: 但这并没有奏效。有这方面的例子吗?如何告诉对象映射器对类使用我的注释?

  • 我需要反序列化以下json: 将它的< code>id属性设置为< code>foo_id json属性。 我需要在自定义反序列化程序中执行此操作。实现这一点最简单的方法是什么? 我想以某种方式将json“转换”为 然后将此委托给杰克逊。 在本例中,对象的类型为Foo,但其他对象可能不属于此类。另外,在本例中,json是一个数字,但如果它也是一个字符串,我希望支持。所以,我需要一种通用的方法来做到

  • 问题内容: 我正在实现RESTful Web服务,其中用户必须与请求一起发送签名的验证令牌,以便可以确保请求不会被中间人篡改。我当前的实现如下。 验证令牌是一个VerifData对象,它序列化为String,然后进行哈希处理和加密。 在我的服务中,我将要序列化的数据放入VerifData的实例中,然后使用Jackson ObjectMapper对其进行序列化,并与验证令牌一起传递给验证引擎。 但是

  • 我正在实现一个RESTful web服务,其中用户必须在请求的同时发送一个签名的验证令牌,这样我就可以确保请求没有被中间人篡改。我当前的实现如下所示。 验证令牌是一个VerifData对象,序列化为字符串,然后进行散列和加密。 有办法绕过这件事吗?我可以指定ObjectMapper要映射的属性的顺序吗(像按升序)?或者是否有任何其他方法可以最好地实现此验证步骤。客户端和服务器实现都是我开发的。我使

  • 主要内容:1 编写核心类,2 运行测试本文讲解如何将一个Java对象序列化为一个json文件,然后读取该json文件读取回对象。在下面的示例中,我们创建Student类。使用Jackson存储到一个student.json文件,该文件拥有Student对象的JSON表示形式。 1 编写核心类 MainApp: 2 运行测试

  • 我对班级结构有如下建议: @JsonTypeInfo(use=JsonTypeInfo.Id.NAME,include=JsonTypeInfo.As.PROPERTY,PROPERTY=“type”) 上面的类被序列化为json元素数组,但是当我反序列化它们时,我想要如下结构: 公共阶层结构{ 是否可以将testA、testB和testC类型的元素数组转换为FlatStructure类的属性?