Map a JSON field (to a value) based on another field (which is a key) using Jackson

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

I have the above JSON (/Users/user1/Desktop/responseMap.json) which is basically a Map<String, MockResponse> where MockResponse is the below POJO:

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

Now, I have another POJO - TestCase, and another JSON - testCase.json as below:

public class TestCase {

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

testCase.json

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

What I am able to do is first map testCase.json to TestCase using Jackson, then map responseMap.json to Map<String, MockResponse>, then in my code search for mockResponseKey in the map.

But what I want to do is when I map testCase.json to TestCase using Jackson, I want the value of variable mockResponse to set automatically based on the value of variable mockResponseKey using the first JSON map.

Michał Ziober :

You need to write custom deserialiser for TestCase class. In custom deserialiser you can parse basic properties: responseMapFileLocation, mockResponseKey and load mockResponse from other file. To deserialiser MockResponse you can use new ObjectMapper instance. Below code shows how this concept could be implemented:

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

You need to implement only toString method for each POJO class. Above code prints:

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

Both JSON files are in resource folder.

See also:

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=148894&siteId=1