Сопоставить поле JSON (со значением) на основе другого поля (которое является ключом) с помощью Джексона - PullRequest
2 голосов
/ 24 мая 2019
{
  "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.json с TestCase, используя Jackson, затем сопоставить responseMap.json с Map<String, MockResponse>, а затем в моем коде найти mockResponseKey на карте.

Но то, что я хочу сделать, это когда я сопоставляю testCase.json с TestCase, используя Jackson, я хочу, чтобы значение переменной mockResponse устанавливалось автоматически на основе значения переменной mockResponseKey с использованием первого JSON карта.

Ответы [ 3 ]

1 голос
/ 24 мая 2019

Настроив метод получения в вашем классе Test и пометив поле как приватное, я смог сделать его динамическим (импорт из пакета 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]]
1 голос
/ 25 мая 2019

Вам необходимо написать собственный десериализатор для класса TestCase.В пользовательском десериализаторе вы можете анализировать основные свойства: responseMapFileLocation, mockResponseKey и загружать 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.

См. Также:

0 голосов
/ 24 мая 2019

То, что вы просите, невозможно только с Джексоном. Джексон - это, прежде всего, инструмент сортировки / сортировки, который преобразует JSON в объекты и наоборот. Другими словами, ценность объекта должна быть известна во время демаршаллинга.

Однако вы можете разархивировать свой JSON как HashMap, используя код:

new JSONObject(map);

найдите MockResponse-as-a-string, используя mockResponseKey, а затем распакуйте этот код в новый MockResponse.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...