使用Jackson将基于另一个字段(这是键)的JSON字段映射到一个值

时间:2019-05-24 17:56:27

标签: java jackson deserialization json-deserialization objectmapper

{
  "key1": {
    "parameter1": "String1",
    "parameter2": "String2"
  },
  "key2": {
    "parameter1": "String3",
    "parameter2": "String4"
  },
  "key3": {
    "parameter1": "String5",
    "parameter2": "String6"
  }
}

我有上面的JSON(/Users/user1/Desktop/responseMap.json),基本上是Map<String, MockResponse>,其中MockResponse是下面的POJO

public class MockResponse {
    public String parameter1;
    public String parameter2;
} 

现在,我有另一个POJO-TestCase和另一个JSON-testCase.json,如下所示:

public class TestCase {

    public String responseMapFileLocation;
    public String mockResponseKey;
    public MockResponse mockResponse;
}

testCase.json

{
  "responseMapFileLocation": "/Users/user1/Desktop/responseMap.json",
  "mockResponseKey": "key1",
  "mockResponse": null
}

我能做的就是首先使用testCase.jsonTestCase映射到Jackson,然后将responseMap.json映射到Map<String, MockResponse>,然后在我的代码中搜索mockResponseKey在地图上。

但是我想做的是,当我使用testCase.jsonTestCase映射到Jackson时,我希望变量mockResponse的值根据的值自动设置。变量mockResponseKey使用第一个JSON映射。

3 个答案:

答案 0 :(得分:0)

仅杰克逊无法满足您的要求。 Jackson主要是一种编组/解组工具,可将JSON转换为对象,反之亦然。换句话说,在解组时必须知道对象的值。

不过,您可以使用以下代码将json解组为HashMap:

new JSONObject(map);

使用mockResponseKey搜索MockResponse-as-a-string,然后将该代码解组为新的MockResponse。

答案 1 :(得分:0)

在您的Test类中调整getter setter并将其标记为private,我能够使它动态化(导入来自org.codehaus.jackson包)

class TestCase {

    private String responseMapFileLocation;

    private String mockResponseKey;

    @JsonIgnore
    private MockResponse mockResponse; //else value will be override in json value

    public String getResponseMapFileLocation() {
        return responseMapFileLocation;
    }
    public void setResponseMapFileLocation(String responseMapFileLocation) {
        this.responseMapFileLocation = responseMapFileLocation;
    }
    public String getMockResponseKey() {
        return mockResponseKey;
    }
    public void setMockResponseKey(String mockResponseKey1) throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        Map<String, MockResponse> map = mapper.readValue(new File("C:\\Users\\Json1.json"), TypeFactory.mapType(HashMap.class, String.class, MockResponse.class));
        this.mockResponse = map.get(mockResponseKey1);
        this.mockResponseKey = mockResponseKey1;
    }
    public MockResponse getMockResponse() {
        return mockResponse;
    }

    @Override
    public String toString() {
        return "TestCase [responseMapFileLocation=" + responseMapFileLocation + ", mockResponseKey=" + mockResponseKey
                + ", mockResponse=" + mockResponse + "]";
    }
}


class MockResponse {
    public String parameter1;
    public String parameter2;
    @Override
    public String toString() {
        return "MockResponse [parameter1=" + parameter1 + ", parameter2=" + parameter2 + "]";
    }
}

并在以下代码下运行

public static void main(String[] args) throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        TestCase testCase = mapper.readValue(new File("C:\\UsersJson2.json"), TestCase.class);
        System.out.println(testCase);

    }

输出将为

TestCase [responseMapFileLocation=/Users/user1/Desktop/responseMap.json, mockResponseKey=key1, mockResponse=MockResponse [parameter1=String1, parameter2=String2]]

答案 2 :(得分:0)

您需要为TestCase类编写自定义反序列化器。在自定义反序列化器中,您可以解析基本属性:responseMapFileLocationmockResponseKey并从其他文件加载mockResponse。要对MockResponse进行反序列化,可以使用新的ObjectMapper实例。下面的代码显示了如何实现此概念:

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.TreeNode;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.type.MapType;

import java.io.File;
import java.io.IOException;
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();

        System.out.println(mapper.readValue(jsonFile, TestCase.class));
    }
}

class MockResponse {
    public String parameter1;
    public String parameter2;
}

@JsonDeserialize(using = TestCaseFromExternalFileDeserializer.class)
class TestCase {

    public String responseMapFileLocation;
    public String mockResponseKey;
    public MockResponse mockResponse;
}

class TestCaseFromExternalFileDeserializer extends JsonDeserializer<TestCase> {

    private final ObjectMapper mapper;
    private final MapType mapType;

    public TestCaseFromExternalFileDeserializer() {
        mapper = new ObjectMapper();
        mapType = mapper.getTypeFactory().constructMapType(Map.class, String.class, MockResponse.class);
    }

    @Override
    public TestCase deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        TreeNode treeNode = p.readValueAsTree();

        TestCase testCase = new TestCase();
        testCase.responseMapFileLocation = ((JsonNode) treeNode.get("responseMapFileLocation")).asText();
        testCase.mockResponseKey = ((JsonNode) treeNode.get("mockResponseKey")).asText();
        parseMockResponse(testCase);

        return testCase;
    }

    private void parseMockResponse(TestCase testCase) throws IOException {
        Map<String, MockResponse> map = mapper.readValue(new File(testCase.responseMapFileLocation), mapType);

        testCase.mockResponse = map.get(testCase.mockResponseKey);
    }
}

您只需为每个toString类实现POJO方法。上面的代码打印出来:

TestCase{responseMapFileLocation='./resource/responseMap.json', mockResponseKey='key1', mockResponse=MockResponse{parameter1='String1', parameter2='String2'}}

两个JSON文件都位于resource文件夹中。

另请参阅: