【问题标题】:How do you convert a Map<Key, Value> into an array of {"keyprop" : key, "valueprop" : value} with Jackson?如何将 Map<Key, Value> 转换为 Jackson 的 {"keyprop" : key, "valueprop" : value} 数组?
【发布时间】:2021-03-17 00:47:31
【问题描述】:

我正在尝试执行以下操作

给定

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 文档,但找不到答案。我会很感激一些帮助。提前致谢!

【问题讨论】:

    标签: java json dictionary serialization jackson


    【解决方案1】:

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

    • 首先定义一个中间POJO:

      public class LanguageInfo {
          private String language;
          private String label;
      }
      
    • 将 map 转换为中间 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并用它来做序列化工作

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

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

      需要上面定义的中间POJOLanguageInfo

      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();
          }
      }
      
    • 其次,将此序列化器注册到 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"
        }
    ]
    

    【讨论】:

    • 您好,感谢您的回答。您是否知道仅使用注释/声明方式来执行此操作,而不是创建包装类?现有的代码库有一个像 LanguageInfos 这样的类,它包含地图作为唯一的属性,我想用我提到的格式序列化这个类
    • @dac1n 你可以定义自己JsonSerializer 来做你想做的事。我已经发布了简单的代码。
    猜你喜欢
    • 1970-01-01
    • 2015-03-22
    • 1970-01-01
    • 2019-08-08
    • 1970-01-01
    • 1970-01-01
    • 2021-12-16
    • 2014-04-23
    • 2012-02-06
    相关资源
    最近更新 更多