【问题标题】:JSON to Java POJO not working for simple structure?JSON to Java POJO 不适用于简单的结构?
【发布时间】:2023-03-18 03:27:01
【问题描述】:

JSON:

{
  "246": {
    "test1": "one" 
  },
  "355": {
    "test2": "two"
  }
}

Java POJO

class POJO{
  private HashMap<String, SubPojo> subMap;

  @JsonAnySetter
  public void addToMap(String key, SubPojo val){ subMap.put(key, value); }
}

class SubPojo{
  private HashMap<String, String> map; 
  @JsonAnySetter
  public void addToMap(String key, String val) { map.put(key, value);}
}

在我的代码中:(使用 Jackson

POJO testing = (new ObjectMapper()).convertValue("path/to/json", POJO.class);

我得到一个例外:

"Unrecognized field `246`..."

我哪里错了?

【问题讨论】:

  • POJO 有一个字段 subMap 但没有 246。因此,您需要告诉对象映射器每个未知字段都应该作为subMap 的键而不是实际属性来处理。如何完成取决于您使用的 json 库。顺便说一句,你需要为SubPojo 做同样的事情。
  • @Thomas,我正在使用 JackSon,你能在这里指导我吗?
  • 基本上你需要使用注解@JsonAnySetter(如果你想序列化为json,@JsonAnyGetter)。
  • 或者,不要定义任何类并解析为Map&lt;String, Map&lt;String, String&gt;&gt;,但您必须使用TypeReference 来防止丢失泛型类型参数。
  • 请注意,如果您的所有对象基本上都是地图,您也可以通过 ObjectMapper.readTree(json) 将该 json 解析为地图或通用树格式。

标签: java json jackson


【解决方案1】:

类似这样的:

public class Pojo {
    private Map<String,Object> map = new HashMap<>();

    @JsonAnySetter
    public void addToMap(String key, Object value) {
        this.map.put(key, value);
    }

    @JsonAnyGetter
    public Map<String,Object> getMap() {
        return map;
    }
}

有一个article on Baeldung 涵盖了各种Jackson 注释,包括这个注释,以及Jackson wiki 的一些基础知识。

【讨论】:

  • 什么我有一个嵌套的值对象,虽然在我的例子中?
【解决方案2】:

您无需创建任何 POJO 类来解析该 JSON 文本,因为它可以解析为 Map&lt;String, Map&lt;String, String&gt;&gt;

您必须使用TypeReference 来防止泛型类型参数丢失。

Map<String, Map<String, String>> data = new ObjectMapper()
        .readValue(new File("test.json"),
                   new TypeReference<Map<String, Map<String, String>>>() {});

使用问题中的 JSON 文本打印 data 地图将显示:

{246={test1=one}, 355={test2=two}}

【讨论】:

  • 是的,我知道,但要求我包装它。
【解决方案3】:

converValue 方法用于转换对象。见JavaDoc:

从给定值进行两步转换的便捷方法, 到给定值类型的实例中,如果(但仅当!)转换是 需要。如果给定的值已经是请求的类型,则返回值 照原样。此方法在功能上类似于给定的第一个序列化 将值转换为 JSON,然后将 JSON 数据绑定到给定类型的值, 但应该更有效,因为完全序列化不需要(需要 发生。但是,相同的转换器(串行器、解串器)将 用于数据绑定,意味着相同的对象映射器配置 有效。

例如,您可以像这样将File“转换”为String

mapper.convertValue(jsonFile, String.class)

其中jsonFileFile 类的一个实例。示例结果可能是:path/to/json

要反序列化 JSON 有效负载,请使用 readValue 方法系列中的一个。

您可以使用带注释的 JsonCreator 构造函数创建您的 POJO

class Pojo {

    private final Map<String, SubPojo> map;

    @JsonCreator
    public Pojo(Map<String, SubPojo> map) {
        this.map = map;
    }

    public Map<String, SubPojo> getMap() {
        return map;
    }

    @Override
    public String toString() {
        return "Pojo{" +
                "map=" + map +
                '}';
    }
}

class SubPojo {

    private Map<String, String> map;

    @JsonCreator
    public SubPojo(Map<String, String> map) {
        this.map = map;
    }

    @Override
    public String toString() {
        return "SubPojo{" +
                "map=" + map +
                '}';
    }
}

而且用法简单。要从文件中读取JSON,请使用readValue 方法:

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.File;
import java.util.Map;

public class JsonApp {

    public static void main(String[] args) throws Exception {
        File jsonFile = new File("./resource/test.json").getAbsoluteFile();

        ObjectMapper mapper = new ObjectMapper();
        Pojo map = mapper.readValue(jsonFile, Pojo.class);
        System.out.println(map);
    }
}

上面的代码打印:

Pojo{map={246=SubPojo{map={test1=one}}, 355=SubPojo{map={test2=two}}}}

如果您想保留您的数据模型,请使用 JsonAnySetter 注释。您的数据模型可能如下所示:

class Pojo {
    private Map<String, SubPojo> subMap = new HashMap<>();

    @JsonAnySetter
    public void addToMap(String key, SubPojo value) {
        subMap.put(key, value);
    }

    @Override
    public String toString() {
        return "POJO{" +
                "subMap=" + subMap +
                '}';
    }
}

class SubPojo {
    private Map<String, String> map = new HashMap<>();

    @JsonAnySetter
    public void addToMap(String key, String value) {
        map.put(key, value);
    }

    @Override
    public String toString() {
        return "SubPojo{" +
                "map=" + map +
                '}';
    }
}

上面的使用示例打印:

POJO{subMap={355=SubPojo{map={test2=two}}, 246=SubPojo{map={test1=one}}}}

【讨论】:

  • 在我的示例中如何进一步使用嵌套?
猜你喜欢
  • 1970-01-01
  • 2016-06-16
  • 1970-01-01
  • 2020-02-10
  • 1970-01-01
  • 1970-01-01
  • 2020-08-23
  • 2018-04-01
  • 1970-01-01
相关资源
最近更新 更多