【问题标题】:spring-boot json root namespring-boot json根名称
【发布时间】:2016-08-13 06:35:45
【问题描述】:

我正在使用 spring-boot 1.3.3 并试图弄清楚如何在 JSON 序列化中使用根名称。例如,我想...

{ stores: [
  {
    id: 1,
    name: "Store1"
  },
  {
    id: 2,
    name: "Store2"
  }]
}

但是我得到了

[
  {
    id: 1,
    name: "Store1"
  },
  {
    id: 2,
    name: "Store2"
  }
]

我一直在查看 @JsonRootName 并自定义 Jackson2ObjectMapperBuilder 配置,但无济于事。在 grails 中,这对于 Json Views 来说非常简单,我还试图看看它是如何直接转换为 spring-boot 的,但似乎仍然无法弄清楚。

我意识到这类似于 this 问题,但我觉得在 Spring(启动)的上下文中它可能会以不同的方式应用,并且想知道如何。

【问题讨论】:

标签: json spring-boot


【解决方案1】:

解决方案 1:Jackson JsonRootName

我一直在看@JsonRootName

自定义 Jackson2ObjectMapperBuilder 配置但无济于事

@JsonRootNameJackson2ObjectMapperBuilder 有哪些错误?

这适用于我的 Spring Boot (1.3.3) 实现:

杰克逊配置 Bean

@Configuration
public class JacksonConfig {
    @Bean
    public Jackson2ObjectMapperBuilder jacksonBuilder() {
        Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
        builder.featuresToEnable(SerializationFeature.WRAP_ROOT_VALUE); 
        // enables wrapping for root elements
        return builder;
    }
}

参考:Spring Documentation - Customizing the Jackson ObjectMapper

将@JsonRootElement 添加到您的响应实体

@JsonRootName(value = "lot")
public class LotDTO { ... }

Json 结果 用于 HTTP-GET /lot/1

{
  "lot": {
    "id": 1,
    "attributes": "...",
    }
}

至少这适用于一个对象的响应。

我还没有弄清楚如何自定义集合中的根名称。 @Perceptions 的回答可能会有所帮助 How to rename root key in JSON serialization with Jackson


编辑

解决方案 2:没有 Jackson 配置

由于我不知道如何使用 Kackson 自定义集合中的 json 根名称

我改编了@Vaibhav 的答案(见2):

自定义 Java 注释

@Retention(value = RetentionPolicy.RUNTIME)
public @interface CustomJsonRootName {
    String singular(); // element root name for a single object
    String plural(); // element root name for collections
}

向 DTO 添加注释

@CustomJsonRootName(plural = "articles", singular = "article")
public class ArticleDTO { // Attributes, Getter and Setter }

在 Spring Controller 中返回 Map 作为结果

@RequestMapping(method = RequestMethod.GET)
public ResponseEntity<Map<String, List<ArticleDTO>>> findAll() {
  List<ArticleDTO> articles = articleService.findAll();
  if (articles.isEmpty()) {
      return new ResponseEntity<>(HttpStatus.NO_CONTENT);
  }
  Map result = new HashMap();
  result.put(ArticleDTO.class.getAnnotation(CustomJsonRootName.class).plural(), articles);
  return new ResponseEntity<>(result, HttpStatus.OK);
}

【讨论】:

    【解决方案2】:

    我找到了一个非常简单的方法来做到这一点。而不是返回一个

    ArrayList<Object>
    

    你的对象到前端,只返回一个

    HashMap<String, ArrayList<Object>>
    

    并通过以下方式初始化对象列表和相应的 HashMap:

    List<Object> objectList = new ArrayList<>();
    

    ...用你的对象填充你的objectList,然后:

    HashMap<String, ArrayList<Object>> returnMap = new HashMap<>();
    returnMap.put("lot", objectList);
    return returnMap;
    

    你的控制器方法的头部看起来像这样:

    @ResponseBody
    @RequestMapping(value = "/link", method = RequestMethod.POST)
    public HashMap<String, List<Object>> processQuestions(@RequestBody List<incomingObject> controllerMethod) {
    

    这将产生所需的 JSON,而无需通过注释或其他方式进行进一步定义。

    【讨论】:

    • 我实际上已经转移到这个确切的模型,唯一的例外是我创建了一个注释来保存根名称的复数版本,因此我可以将它作为地图中的键而不是硬编码字符串。
    【解决方案3】:

    我认为最简单的方法是返回Map &lt;String, Object&gt;。 只需将键作为“商店”,将对象作为存储对象。

    前-

    Map<String, Object> response = new LinkedHashMap<String, Object>();
    
    
    response.put("stores", stores)
    

    【讨论】:

      【解决方案4】:

      SpringBoot 使用 Jackson 作为 json 工具,所以这会很好用:

      @JsonTypeName("stores")
      @JsonTypeInfo(include = JsonTypeInfo.As.WRAPPER_OBJECT, use = JsonTypeInfo.Id.NAME)
      public class stores { 
          ...
      }
      

      【讨论】:

      • 这是迄今为止最好的,它更短而且非常灵活,谢谢!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-12-27
      • 1970-01-01
      • 2016-12-02
      • 2019-04-06
      • 1970-01-01
      • 1970-01-01
      • 2018-02-25
      相关资源
      最近更新 更多