【问题标题】:Spring Boot - Returning JSON with array of objectsSpring Boot - 返回带有对象数组的 JSON
【发布时间】:2020-02-11 18:46:33
【问题描述】:

使用answer 作为提示,我为/greetings 开发了一个 Spring Boot 控制器,以 JSON 格式返回不同语言的问候语。

当我得到我想要的格式(对象数组)的输出时,如果有更好的方法,请告诉我?

package com.example.demo;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.HashMap;

@RestController
public class GreetingController {
    @GetMapping("/greetings")
    public HashMap<String, Object> getGreeting() {
        ArrayList<Object> al = new ArrayList<Object>();
        HashMap<String, String> map1 = new HashMap<String, String>();
        map1.put("en", "Greetings!");
        al.add(map1);
        HashMap<String, String> map2 = new HashMap<>();
        map2.put("hi", "Namaste!");
        al.add(map2);
        //
        HashMap<String, Object> finalMap = new HashMap<>();
        finalMap.put("all", al);
        return finalMap;
    }
}

收到(有效)输出:

{
    "all": [
        {
            "en": "Greetings!"
        },
        {
            "hi": "Namaste!"
        }
    ]
}

【问题讨论】:

    标签: java json rest spring-boot


    【解决方案1】:

    如果您只需要对象数组,则不应选择 map 而应使用 List 类型。例如,如果您有 Greeting 对象并且想要返回所有问候的列表,您的 GetMapping 将如下所示:

    @GetMapping("/greetings")
        public ResponseEntity<List<Map<String,String>>> getGreeting() {
            ArrayList<Object> al = new ArrayList<Object>();
            HashMap<String, String> map1 = new HashMap<String, String>();
            map1.put("en", "Greetings!");
            al.add(map1);
            HashMap<String, String> map2 = new HashMap<>();
            map2.put("hi", "Namaste!");
            al.add(map2);
            return ResponseEntity.ok(al);
        }
    

    使用ResponseEntity 可确保您返回正确的状态代码,并且在结束您的响应时,它更易于维护。

    编辑:对于您使用 map 创建的键值对,您可以使用 POJO。

    class Greeting{
       private String greetingLangCode;
       private String greetingText;
       // getters and setters
    
     @JsonValue
    public String info(){
     return this.greetingLangCode + ":" + "greetingText";
    }
    }
    

    随着这个端点的变化

        @GetMapping("/greetings")
        public ResponseEntity<List<Greeting>> getGreeting() {
            List<Greeting> al = new ArrayList<>();
            al.add(new Greeting("en", "Greetings!"));
            al.add(new Greeting("hi", "Namaste!"));
            return ResponseEntity.ok(al);
        }
    

    但如果上述方法不起作用,您将需要一个自定义序列化程序来像 map 的 key:value 对那样序列化。

    this 的帖子可能很有帮助。这篇文章有一个如何编写自定义serializerdeserializer 的完整示例。

    【讨论】:

    • 那么,添加个人HashMap&lt;String, String&gt; 是填充List 的唯一方法吗?顺便说一句,您可能想要编辑 &lt;List&lt;Student&gt;&gt; 部分。
    • 谢谢!不,其他方式是您可以实际使用 POJO。更新学生部分,因为我正在考虑举这个例子
    • 能否添加一个 POJO 示例?
    • 已添加示例,以及发布链接以防 JsonValue 注释不起作用,这有助于编写自定义序列化器和反序列化器。
    【解决方案2】:

    虽然您可以使用嵌套的 ListMap 对象,但您的代码很快就会变得不可读。最好创建实际对象。例如:

    public class TranslatedGreeting {
      private String language;
      private String greeting;
    
      public TranslatedGreeting(String language, String greeting) {
        this.language = language;
        this.greeting = greeting;
      }
    
      // add getters
    }
    

    然后在控制器中使用它:

    @RestController
    public class GreetingController {
    
      @GetMapping("/greetings")
      public List<TranslatedGreeting> greetings() {
        List<TranslatedGreeting> result = new ArrayList<>();
        result.add(new TranslatedGreeting("en", "Greetings!"));
        result.add(new TranslatedGreeting("hi", "Namaste!");
        return result;
      }
    }
    

    生成的 JSON 将如下所示:

    [
      {"language":"en","greeting":"Greetings!"},
      {"language":"hi","greeting":"Namaste!"},
    ]
    

    这种 JSON 结构也更容易为客户端解析,因为密钥固定在 languagegreeting

    如果您真的想保留原始结构,请像这样声明自定义序列化程序:

    @JsonComponent
    public class TranslatedGreetingSerializer extends JsonSerializer<TranslatedGreeting> {
        @Override
        public void serialize(TranslatedGreeting translatedGreeting, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
            jsonGenerator.writeStartObject();
            jsonGenerator.writeStringField(translatedGreeting.getLanguage(), translatedGreeting.getGreeting());
            jsonGenerator.writeEndObject();
        }
    }
    

    这将输出:

    [
      {
        "en": "Greetings!"
      },
      {
        "hi": "Namaste!"
      }
    ]
    

    【讨论】:

    • 但它失去了 OP 所期望的紧凑 json 结构。同样,我刚刚分享了使用 POJO 时如何解决此问题。
    猜你喜欢
    • 2021-03-25
    • 1970-01-01
    • 1970-01-01
    • 2021-03-09
    • 1970-01-01
    • 2019-03-08
    • 2019-07-12
    • 2019-03-27
    • 2018-01-25
    相关资源
    最近更新 更多