你如何使用 Jackson 将 Map<Key, Value> 转换为 {"keyprop" : key, "valueprop" : value} 的数组?

How do you convert a Map<Key, Value> into an array of {"keyprop" : key, "valueprop" : value} with Jackson?

我正在尝试执行以下操作

给出

Map<String, String> labels = {"en_GB" : "English", "de" : "German", "it" : "Italian"}....

我想用Jackson序列化到

[{"language" : "en_GB", "label" : "English"}, {"language" : "de", "label" : "German"}, {"language" : "it", "label" : "Italian"}]

本质上将映射拆分为对象数组,键和值作为单独的属性

而不是

 {"en_GB" : "English", "de" : "German", "it" : "Italian"}

我已经搜索了整个 Jackson 文档,但我找不到这个问题的答案。我会很感激一些帮助。提前致谢!

方法一:定义一个中间POJO,将map转换为中间对象列表

  • 先定义一个中间的POJO:

    public class LanguageInfo {
        private String language;
        private String label;
    }
    
  • 将映射转换为中间 POJO 列表并将列表序列化为字符串:

    Map<String, String> labels = new HashMap<>();
    labels.put("en_GB", "English");
    labels.put("de", "German");
    labels.put("it", "Italian");
    
    List<LanguageInfo> languageInfoList = labels.entrySet().stream()
      .map(entry -> {
          LanguageInfo info = new LanguageInfo();
          info.setLabel(entry.getValue());
          info.setLanguage(entry.getKey());
          return info;
      }).collect(Collectors.toList());
    ObjectMapper mapper = new ObjectMapper();
    System.out.println(mapper.writeValueAsString(languageInfoList));
    

输出为:

[
    {
        "language":"de",
        "label":"German"
    },
    {
        "language":"en_GB",
        "label":"English"
    },
    {
        "language":"it",
        "label":"Italian"
    }
]

方法二:定义一个JsonSerializer并用它来做序列化工作

假设你想直接序列化下面的class:

@Data
public class LanguageInfos {
    private Map<String, String> labels;
}
  • 首先,定义一个JsonSerializer来序列化LanguageInfos:

    需要中间POJO LanguageInfo定义如上:

    public class LanguageInfosJsonSerializer extends JsonSerializer<LanguageInfos> {
    
        @Override
        public void serialize(LanguageInfos languageInfos, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
            // LanguageInfo defined in below code
            List<LanguageInfo> languageInfoList = languageInfos.getLabels().entrySet().stream()
                .map(entry -> {
                    LanguageInfo info = new LanguageInfo();
                    info.setLabel(entry.getValue());
                    info.setLanguage(entry.getKey());
                    return info;
                }).collect(Collectors.toList());
            jsonGenerator.writeObject(languageInfoList);
        }
    }
    

    不需要中间POJO:

    public class LanguageInfosJsonSerializer extends JsonSerializer<LanguageInfos> {
    
        @Override
        public void serialize(LanguageInfos languageInfos, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
            jsonGenerator.writeStartArray(languageInfos.getLabels().size());
            languageInfos.getLabels().entrySet().forEach(new Consumer<Map.Entry<String, String>>() {
                @SneakyThrows
                @Override
                public void accept(Map.Entry<String, String> entry) {
                        ObjectNode node = new ObjectMapper().createObjectNode();
                        node.put("language",entry.getKey());
                        node.put("label",entry.getValue());
                        jsonGenerator.writeObject(node);
                }
            });
            jsonGenerator.writeEndArray();
        }
    }
    
  • 其次,将这个Serializer注册到一个ObjectMapper对象中:

    SimpleModule simpleModule = new SimpleModule();
    simpleModule.addSerializer(LanguageInfos.class, new LanguageInfosJsonSerializer());
    ObjectMapper mapper = new ObjectMapper();
    mapper.registerModule(simpleModule);
    
  • 三、直接使用ObjectMapper序列化:

    Map<String, String> labels = new HashMap<>();
    labels.put("en_GB", "English");
    labels.put("de", "German");
    labels.put("it", "Italian");
    
    LanguageInfos languageInfos = new LanguageInfos();
    languageInfos.setLabels(labels);
    
    ObjectMapper mapper = new ObjectMapper();
    SimpleModule simpleModule = new SimpleModule();
    simpleModule.addSerializer(LanguageInfos.class, new LanguageInfosJsonSerializer());
    mapper.registerModule(simpleModule);
    System.out.println(mapper.writeValueAsString(languageInfos));
    

输出为:

[
    {
        "language":"de",
        "label":"German"
    },
    {
        "language":"en_GB",
        "label":"English"
    },
    {
        "language":"it",
        "label":"Italian"
    }
]