繁体   English   中英

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

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

我得到的返回结果可能如下所示:

{"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"}]}

或像这样:

{"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”}]}

因此,我正在调用rest服务,返回结果将始终以行开头:然后是看起来像Dictionary或Map / HaspMap值的数组。 该词典的大小将有所不同。 但是在该行列表中,它似乎是键值对。

现在,我尝试将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;
    }
}

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;
    }
}

我这样调用上面的代码:

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

我已经尝试了上面的各种配置,但似乎没有抛出无法识别的字段异常就无法使其返回。 这是有道理的,因为Key值中的第一个元素被视为映射器无法映射的字段,因为它没有在我要映射到的对象中的任何位置定义。
将此List>映射到对象的适当方法是什么? 有没有一种简单的方法可以将值也转换为适当的类型? 我使用的是jackson-databind,但如果有解决方案,可以说服他使用GSON。

好吧,显然这是行不通的,因为杰克逊无法将键/值对映射到给定的映射。 如果要让杰克逊进行映射,请在JSON中将属性定义为DTO中的类字段。 但这似乎违反直觉,因为在给定的两个不同有效负载中您具有不同的属性,它们的结构也不同。 因此,这就是您应该做的。 让我们将每个对象表示为JSON键/值对与数组中对象的偏移值的映射。 这样也可以解决您的有效负载的动态特性。 代码看起来像这样。

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);

输出如下:

{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}}

对于每个对象,将针对该特定对象在数组中的相对偏移量打印键/值映射。 如果需要,您可以尝试使用Gson ,但这是足够简单的IMO。

本质上,我指望杰克逊图书馆变得聪明。 我需要遍历返回的Json的“树结构”。 将其映射到我的个人Response对象。 有点像这样:

            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);

不用担心,我将其包装在try catch块中。

暂无
暂无

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

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