简体   繁体   English

反序列化JSon String int List的正确方法 <Map<String, Object> &gt;

[英]Proper way to Deserialize JSon String int List<Map<String, Object>>

I have a return result that can look like this: 我得到的返回结果可能如下所示:

{"rows":[{"ProfileID":"SLappE","CR_ProfileID":"BC1A"},{"ProfileID":"SCRA","CR_ProfileID":"BC15"},{"ProfileID":"SMOKE","CR_ProfileID":"BC15"},{"ProfileID":"Smokey","CR_ProfileID":"BC1F"},{"ProfileID":"WF-LN-OCR","CR_ProfileID":"BC1F"}]}

Or like this: 或像这样:

{"rows":[{"PARAM":"product_reference_nr","FIELDNAME":"account_nr","EXAMPLE-FIELD":"CHK","EXAMPLE-TABLE":"CHK_DOC","ID":"CHK-ACCT"},{"PARAM":"party_pd_nr","FIELDNAME":"front_image_object_id","EXAMPLE-FIELD":"CHK","EXAMPLE-TABLE":"BACK_CHK_DOC","ID":"CHK-BACK"},{"PARAM":"endDate","FIELDNAME":"document_dt","EXAMPLE-FIELD":"HR","EXAMPLE-TABLE":"SPLAPSTIC_DOC","ID":"HR-DT"},{"PARAM":"startDate","FIELDNAME":"document_dt","EXAMPLE-FIELD":"HR","EXAMPLE-TABLE":"SPLAPSTIC_DOC","ID":"HR-DT-STARTDT"},{"PARAM":"formCode","FIELDNAME":"form_category_cd","EXAMPLE-FIELD":"HR","EXAMPLE-TABLE":"SPLAPSTIC_DOC","ID":"HR-FORM”}]}

So I am calling a rest service and the return result will always start with rows: which is then followed by an array of what appear to be Dictionary or Map/HaspMap values. 因此,我正在调用rest服务,返回结果将始终以行开头:然后是看起来像Dictionary或Map / HaspMap值的数组。 The size of that dictionary will vary. 该词典的大小将有所不同。 But in that List of Rows it appears to be key value pairs. 但是在该行列表中,它似乎是键值对。

Now I try to Deserialize that json into this Data Structure: 现在,我尝试将json反序列化为以下数据结构:

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;

import javax.xml.bind.annotation.XmlRootElement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@JsonInclude(JsonInclude.Include.NON_NULL)
@XmlRootElement
public class EResponse {

    @JsonProperty("rows")
    private final List<Row> rows = new ArrayList<>();

    public List<Row> getRows() {
        List<Row> retResult = rows;
        return retResult;
    }
}

and

import com.fasterxml.jackson.annotation.*;

import javax.xml.bind.annotation.XmlRootElement;
import java.util.Hashtable;
import java.util.Map;

@JsonInclude(JsonInclude.Include.NON_NULL)
@XmlRootElement
public class Row {
    private Map<String,Object> column;

    @JsonProperty
    public Map<String, Object> getColumn(){
        return column;
    }
}

I call the above code like so: 我这样调用上面的代码:

result = mapper.readValue(response.readEntity(String.class), new TypeReference<EResponse>(){});

I have tried various configurations of the above and I can't seem to get it to return without throwing an Unrecognized field exception. 我已经尝试了上面的各种配置,但似乎没有抛出无法识别的字段异常就无法使其返回。 Which would make sense as it the first element in the Key value is being seen as a field which the mapper can't map, cause it isn't defined anywhere in the object I am mapping it to. 这是有道理的,因为Key值中的第一个元素被视为映射器无法映射的字段,因为它没有在我要映射到的对象中的任何位置定义。
What is the appropriate way To map this List> to Objects? 将此List>映射到对象的适当方法是什么? Is there a simply way I can Cast the value to the appropriate type as well? 有没有一种简单的方法可以将值也转换为适当的类型? I am using jackson-databind but could be persuaded to use GSON if there is an elegant solution to solve this. 我使用的是jackson-databind,但如果有解决方案,可以说服他使用GSON。

Well, obviously it does not work since jackson can't map the key/value pairs to the given map. 好吧,显然这是行不通的,因为杰克逊无法将键/值对映射到给定的映射。 If you want jackson to map this, define the properties in json as class fields in your DTO. 如果要让杰克逊进行映射,请在JSON中将属性定义为DTO中的类字段。 But that seems counter intuitive since you have different properties in two different payloads given, their structure is different. 但这似乎违反直觉,因为在给定的两个不同有效负载中您具有不同的属性,它们的结构也不同。 So, this is what you should do. 因此,这就是您应该做的。 Let's represent each object as a map of json key/value pairs against the offset value of the object in the array. 让我们将每个对象表示为JSON键/值对与数组中对象的偏移值的映射。 So that will address the dynamic nature of your payload too. 这样也可以解决您的有效负载的动态特性。 The code looks like this. 代码看起来像这样。

final String jsonArray = new String(Files.readAllBytes(Paths.get("./src/main/resources/payload.json")));

final TypeReference<Map<String, String>> typeRef = new TypeReference<Map<String, String>>() {
};
Iterator<Map<String, String>> it = new ObjectMapper().readerFor(typeRef)
        .readValues(JsonPath.parse(jsonArray).read("rows").toString());
final AtomicInteger counter = new AtomicInteger();
Map<Integer, Map<String, String>> mapByObject = new HashMap<>();
it.forEachRemaining(keyValueMap -> {
    mapByObject.putIfAbsent(counter.incrementAndGet(), keyValueMap);
});
System.out.println(mapByObject);

The output is like so: 输出如下:

{1={ProfileID=SLappE, CR_ProfileID=BC1A}, 2={ProfileID=SCRA, CR_ProfileID=BC15}, 3={ProfileID=SMOKE, CR_ProfileID=BC15}, 4={ProfileID=Smokey, CR_ProfileID=BC1F}, 5={ProfileID=WF-LN-OCR, CR_ProfileID=BC1F}}

For each object, key/value map is printed against the relative offset of that particular object in the array. 对于每个对象,将针对该特定对象在数组中的相对偏移量打印键/值映射。 You may try using the Gson if needed, but this is simple enough IMO. 如果需要,您可以尝试使用Gson ,但这是足够简单的IMO。

Essentially, I was counting on the Jackson library to be to smart. 本质上,我指望杰克逊图书馆变得聪明。 I needed to loop through the 'Tree structure' of the Json that was returned. 我需要遍历返回的Json的“树结构”。 Map it to my individual Response objects. 将其映射到我的个人Response对象。 A little like this: 有点像这样:

            ObjectMapper mapper = new ObjectMapper();
        JsonNode rootNode = mapper.readTree(response.readEntity(String.class));
        JsonNode rowsNode = rootNode.path("rows");
        Iterator<JsonNode> elements = rowsNode.elements();
        while (elements.hasNext()){
            JsonNode columnNodes = elements.next();
            System.out.println("All the Column Values: " + columnNodes.asText());
            Map<String, Object> values = new HashMap<String, Object>();
            values = mapper.treeToValue(columnNodes, HashMap.class);
            ERow row = new ERow();
            row.setColumn(values);
            columns.add(row);
        }
        result.setRows(columns);

Don't worry, I wrap that in a try catch block. 不用担心,我将其包装在try catch块中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM