Java - 使用杰克逊将 json 转换为复杂对象

Posted

技术标签:

【中文标题】Java - 使用杰克逊将 json 转换为复杂对象【英文标题】:Java - convert json to complex object using jakson 【发布时间】:2018-07-25 20:14:36 【问题描述】:

这可能会重复问题,但我已经搜索了很多解决方案,但没有运气。 我有一个像下面这样的类:

public class RestartMapState 

    public RestartMapState(List<MapStepData> vMapStepData, List<AbstractMap.SimpleEntry<String,String>> vResolvedParameters, String vJobID)
        this.vJobID=vJobID;
        this.vResolvedParameters = vResolvedParameters;
        this.vMapStepData = vMapStepData;
    

    public RestartMapState()

    private List<MapStepData> vMapStepData;
    public void setvMapStepData(List<MapStepData> mapStepData) this.vMapStepData = mapStepData; 
    public List<MapStepData> getvMapStepData()
        return this.vMapStepData;
    

    private List<AbstractMap.SimpleEntry<String,String>> vResolvedParameters;
    public List<AbstractMap.SimpleEntry<String,String>> getvResolvedParameters()  return this.vResolvedParameters; 
    public void setvResolvedParameters(List<AbstractMap.SimpleEntry<String,String>> resolvedParameters) this.vResolvedParameters = resolvedParameters; 

    private String vJobID;
    public String getvJobID() return this.vJobID; 
    public void setvJobID(String jobID) this.vJobID = jobID; 

当我尝试使用以下代码对 json 进行此操作时,我正在获取 json 文件。

RestartMapState vRestartMapState = new RestartMapState(vRemainingStepsToBeExecuted, vMapResolvedParameters, vMapExCtx.getvJobID());
try 
    vObjectMapper.writerWithDefaultPrettyPrinter().writeValue(stateFile, vRestartMapState);
 catch (JsonGenerationException e) 
    isSerialized = false;
    e.printStackTrace();
 catch (JsonMappingException e) 
    isSerialized = false;
    e.printStackTrace();
 catch (IOException e) 
    isSerialized = false;
    e.printStackTrace();

我的 JSON 文件如下所示:


  "vMapStepData" : [ 
    "dependsOn" : null,
    "orderIndex" : 0,
    "name" : "Step1",
    "mapStepId" : 167119,
    "sqlstatements" : 
      "sqlstatement" : [ 
        "value" : "-- Map Step   (Step1)\nCREATE TABLE ##!sessionid##Step1\n    AS\nSELECT currency_nbr AS currency_nbr,...",
        "orderIndex" : 1,
        "isQuery" : false,
        "flags" : [ "PartOfCore" ]
       ]
    
  , 
    "dependsOn" : null,
    "orderIndex" : 1,
    "name" : "Step2",
    "mapStepId" : 237822,
    "sqlstatements" : 
      "sqlstatement" : [ 
        "value" : "\n\n-- Map Step   (Step2)\nCREATE TABLE ##!sessionid##Step2\n    AS\nSELECT country_cd AS ....",
        "orderIndex" : 1,
        "isQuery" : false,
        "flags" : [ "PartOfCore" ]
       ]
    
   ],
  "vResolvedParameters" : [ 
    "key" : "##RUNDATE##",
    "value" : "2018045"
  , 
    "key" : "##julian##",
    "value" : "2018033"
   ],
  "vJobID" : "10012"

但是当我尝试将相同的 json 文件反序列化为 RestartMapState 类型的对象时,我收到以下错误。

org.codehaus.jackson.map.JsonMappingException: No suitable constructor found for type [simple type, class java.util.AbstractMap$SimpleEntry<java.lang.String,java.lang.String>]: can not instantiate from JSON object (need to add/enable type information?)
 at [Source: C:\Users\vkukk1\.MAP_STATE_System_Test_Group_Vasu_Test_2_10012.json; line: 30, column: 5] (through reference chain: com.aexp.idn.magellan.RestartMapState["vResolvedParameters"]) RestartMapState vRestartMapState = null;

谁能帮我解决这个问题,我做错了什么?

【问题讨论】:

添加MapStepData类的代码 【参考方案1】:

AbstractMap.SimpleEntry 类没有默认构造函数(没有参数),无法反序列化。 您应该将vResolvedParameters 的泛型类型从AbstractMap.SimpleEntry&lt;String,String&gt; 更改为其他类型:

private List<Pair<String, String>> vResolvedParameters;
public List<Pair<String, String>> getvResolvedParameters() 
    return this.vResolvedParameters;

public void setvResolvedParameters(List<Pair<String, String>> resolvedParameters) 
    this.vResolvedParameters = resolvedParameters;

Pair 在哪里:

private static class Pair<K, V> 
    private K key;
    private V value;

    public K getKey() 
        return key;
    
    public void setKey(K key) 
        this.key = key;
    
    public V getValue() 
        return value;
    
    public void setValue(V value) 
        this.value = value;
    
    ...

您可以使用许多其他库中的 Pair 实现。

或者如果"key" 的值是唯一的,您可以将vResolvedParameters 类型更改为Map&lt;String,String&gt;。但是您的 JSON 格式将从:

...
"vResolvedParameters" : [ 
  "key" : "##RUNDATE##",
  "value" : "2018045"
, 
  "key" : "##julian##",
  "value" : "2018033"
 ],
...

到:

...
"vResolvedParameters": 
  "##RUNDATE##": "2018045",
  "##julian##": "2018033"
,
...

Related qestion

【讨论】:

即使我更改为 Map,我也会收到以下异常:-org.codehaus.jackson.map.JsonMappingException:无法在 [来源:C :\Test_2_10012.json;行:28,列:6](通过引用链:com.aexp.idn.magellan.RestartMapState["vResolvedParameters"]) 顺便说一句,我没有在任何地方使用 LinkedHashMap,我不知道为什么会出现这个异常【参考方案2】:

我终于解决了这个问题。问题在于 vResolvedParameter 的 getter 方法。我已将 getter 方法更改如下:

private List<MapStepData> vMapStepData;
public void setvMapStepData(List<MapStepData> mapStepData) this.vMapStepData = mapStepData; 
public List<MapStepData> getvMapStepData() return this.vMapStepData; 

private Map<String,String> vResolvedParameters;
public Map<String,String> getvResolvedParameters()  return this.vResolvedParameters; 

谢谢@Nokolay。

【讨论】:

以上是关于Java - 使用杰克逊将 json 转换为复杂对象的主要内容,如果未能解决你的问题,请参考以下文章

如何使用骆驼杰克逊将 JSONArray 转换为对象列表

停止杰克逊读数字作为字符串

将JSONObject转换为Map

Java - 使用jackson将json转换为复杂对象

Java—Json数据格式转换需要的Jar包

序列化对象时如何强制杰克逊将数字写为字符串