【问题标题】:Dynamic serialization/deserialization动态序列化/反序列化
【发布时间】:2017-08-29 14:12:47
【问题描述】:

我使用 Spring MVC 和 Jackson 来驱动我工作的应用程序的 API。我面临以下情况,我们需要以两种不同的方式序列化下面的 Person 类...

@Entity
Order{
    String id;
    String name;
    String address;
    List<Items> items;
}

@Entity
Item{
    String id;
    String description:
}

这两种情况取决于“items”字段的内容是否与被调用的服务相一致。

例如,服务http://localhost/order,结果没有“项目”字段。

{
 "id": "1", 
 "name" : "Bill",
 "address" : "any address",
}

另一方面,第二种方式是http://localhost/order/[id_order]/item/[ids_items],结果是在参数上给出的字段“items”。

{
 "id": "1", 
 "name" : "Bil",
 "address" : "any",
 "items" : [{
          "id" : "33",
          "description" : "Item 33"
      }]
}

【问题讨论】:

  • 为什么您对item 的REST 请求没有返回item,而是返回order
  • @Michael 该要求指定路由http://localhost/order/[id_order]/item/[ids_items] 应返回orderitems 列表。这意味着它也存在路由http://localhost/item/[id_item],但它并不关心。

标签: java json spring-mvc serialization jackson


【解决方案1】:

@JsonView

您可以使用@JsonView 根据序列化的上下文过滤字段。是supported by Spring MVC

首先定义你的观点:

public class View {         
    interface Default { }  
    interface Detailed extends Default { }   
}

然后使用所需的视图注释您的字段:

@Entity
public class Order {

    @JsonView(View.Default.class)
    private String id;

    @JsonView(View.Default.class)
    private String name;

    @JsonView(View.Default.class)
    private String address;

    @JsonView(View.Detailed.class)
    private List<Items> items;

    // Getters and setters
}

最后注释你的控制器方法以在序列化响应时使用视图:

@JsonView(View.Default.class) 
@RequestMapping(value = "/order", method = RequestMethod.GET)  
public ResponseEntity<Order> getOrder() {
    ... 
}

@JsonView(View.Detailed.class)
@RequestMapping(value = "/order-with-items", method = RequestMethod.GET)  
public ResponseEntity<SampleResults> getOrderWithItems() {
    ... 
}

为了使其正常工作,您可能需要在 ObjectMapper 中禁用 默认视图包含

mapper.disable(MapperFeature.DEFAULT_VIEW_INCLUSION);

【讨论】:

  • 谢谢@Cassio,我会试一试,很快就会回来。
  • 它就像一个魅力......我发现的困难是如何注释父字段。例如,Order 类扩展了 Resource 类,其中包含一些字段,如 editDate、createDate 和 Id。该类与Item 类和许多其他实体共享。注释所有这些类是很多工作,我需要为每个类创建视图。你知道如何使用更有效吗?非常感谢
  • @Rbi-u-b 我了解您的 original 问题已得到回答,因此我的回答应标记为已接受。如果您还有其他问题,ask a new question 提供所有相关详细信息,我很乐意为您提供帮助。
  • @Rbi-u-b 但是为了解决您的问题,您可能不需要为每个类创建一个视图。您可以为视图使用通用名称,例如 SummaryDetailed
【解决方案2】:

使用 jackson,您可以即时修改结果 json 字符串。例如:

    // create a new order
    Order order = new Order("id", "name", "addr");
    ObjectMapper mapper = new ObjectMapper();

    // create a json string with the order
    JsonNode node = mapper.valueToTree(order);
    //the content of the node at this moment is:
    //{"id":"id","name":"name","address":"addr"}

    // create an ArrayList with the Items
    ArrayList<Item> items = new ArrayList<Item>();
    items.add(new Item("id1", "desc1"));
    items.add(new Item("id2", "desc2"));

    // transform the ArrayList to a json string and add it 
    // the the previous node with the Order
    ((ObjectNode)node).put("items", mapper.valueToTree(items));
    String jsonString = node.toString();
    System.out.println(jsonString);

最终输出为:

{"id":"id","name":"name","address":"addr","items":[{"id":"id1","description":"desc1"},{"id":"id2","description":"desc2"}]}

更多信息请访问官方文档页面:https://github.com/FasterXML/jackson-databind/

【讨论】:

  • 谢谢,这种方式看起来更接近需求,但它是放在控制器中,或者我可以在国外使用它,例如在一些注释中?
  • @AmanM 您可以放入控制器中,或者您可以使用 AOP 来转换您的返回值。
  • 工作量很大。考虑@JsonViews,如我的answer 中所述。
  • @cassiomazzochimolin 我同意,他应该同意你的回答。
  • 当然,@JsonView 注释的工作量较少,这具体响应了我的需求。
猜你喜欢
  • 1970-01-01
  • 2015-11-22
  • 2021-09-14
  • 1970-01-01
  • 2011-05-03
  • 2020-06-07
  • 2019-12-20
  • 1970-01-01
相关资源
最近更新 更多