Leia a data como um array inteiro de json e mapeie com POJO como um inteiro

Sep 22 2020

Estou recebendo json da api rest e quero armazenar os dados na lista do POJO. Abaixo está o código para o mesmo:

public List<myObject> mapper(){

    String myObjectData= restClient.getAllOriginal("myObject");

    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    objectMapper.configure(DeserializationConfig.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);

    
    List<CommitmentPojo> resultDto = null;

    try
    {

        Map<String, List<MyObject>> root = mapper.readValue(jsonString, new TypeReference<Map<String, List<MyObject>>>() {});
        List<MyObject> objects = root.get("myObject");
        
    }
    catch (JsonParseException e)
    {
        e.printStackTrace();
    }
    catch (JsonMappingException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return resultDto;
}

Método que obtém a string da API restante:

public  String getAllOriginal(String resourcePath) {
       // Objects.requireNonNull(this.baseUri, "target cannot be null");
        return this.client
                .target("http://comtsrvc.ny.qa.flx.nimbus.gs.com:3802/v2/")
                .path(resourcePath)
                .request(MediaType.APPLICATION_JSON_TYPE)
                .cookie("mySSO", getCookie())
                .get()
                .readEntity(String.class);
    }

Abaixo está o meu json:

{
  
  "myObject" : [ {
    "key" : {
      "srcSys" : "REPO_1",
      "srcSysRef" : "20200909_1911_1"
    },
    "productData" : {
      "id" : null,
      "number" : null,
      "isn" : null,
      "productId" : null,
      "productAdditionalData" : {
        "assetClassTree" : "UNCLASSIFIED",
        "description" : "UNCLASSIFIED",
        "productTypeData" : {
          "productType" : "UNCLASSIFIED",
          "productGroup" : "UNCLASSIFIED"
        }
      }
    },
    "state" : "OPEN",
    "type" : "01"
  }, {
    "key" : {
      "srcSys" : "REPO_2",
      "srcSysRef" : "20200403_3892_1"
    },
    "productData" : {
      "id" : "1",
      "number" : "11",
      "isn" : "null",
      "productId" : 1234,
      "productAdditionalData" : {
        "assetClassTree" : "xyz",
        "description" : "abc",
        "productTypeData" : {
          "productType" : "UNCLASSIFIED",
          "productGroup" : "UNCLASSIFIED"
        }
      }
    },
    "state" : "OPEN",
    "startDate" : [2020, 9, 22],
    "endDate" : [2020, 9, 24],
    "tradAcctType" : "01"
  } ]
  }

Desde que eu não possa modificar o POJO existente (a menos e até que seja necessário), pois ele precisará de muitas modificações. Estou confuso sobre como acessar a data da matriz e mapeá-la para POJO, onde startDate tem tipo de dados inteiro.

Respostas

2 KousikMandal Sep 22 2020 at 09:09

É possível definir um construtor anotado com @JsonCreator em POJO e, em seguida, analisar a lista de campos de data em json?

Algo parecido com isso.

Test.java

import java.util.List;

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

public class Test {
    private String state;
    private int startDate;
    private int endDate;

    @JsonCreator
    public Test(@JsonProperty("startDate") List<Integer> startDate,
            @JsonProperty("endDate") List<Integer> endDate) {
        StringBuilder stringBuilder = new StringBuilder();
        for (Integer value : startDate) {
            stringBuilder.append(value);
        }
        this.startDate = Integer.parseInt(stringBuilder.toString());
        stringBuilder.setLength(0);
        for (Integer value : endDate) {
            stringBuilder.append(value);
        }
        this.endDate = Integer.parseInt(stringBuilder.toString());
    }

    /**
     * @return the state
     */
    public String getState() {
        return state;
    }

    /**
     * @param state
     *            the state to set
     */
    public void setState(String state) {
        this.state = state;
    }

    /**
     * @return the startDate
     */
    public int getStartDate() {
        return startDate;
    }

    /**
     * @param startDate
     *            the startDate to set
     */
    public void setStartDate(int startDate) {
        this.startDate = startDate;
    }

    /**
     * @return the endDate
     */
    public int getEndDate() {
        return endDate;
    }

    /**
     * @param endDate
     *            the endDate to set
     */
    public void setEndDate(int endDate) {
        this.endDate = endDate;
    }
}

Main.java

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

public class Main {
    public static void main(String[] args) {
        String json = "{\"state\" : \"OPEN\", \"startDate\" : [2020, 9, 22], \"endDate\" : [2020, 9, 24]}";

        ObjectMapper mapper = new ObjectMapper();
        try {
            Test test = mapper.readValue(json, Test.class);
            System.out.println(test.getStartDate() + "   " + test.getEndDate()
                    + "   " + test.getState());
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }
}

Resultado:

2020922   2020924   OPEN

Se a atualização da classe POJO não for possível, há outra maneira alternativa de implementar um desserializador personalizado. Onde você pode implementar uma lógica de conversão semelhante.

Abordagem de desserialização personalizada

CustomTest.java

public class CustomTest {
    private String state;
    private int startDate;
    private int endDate;

    /**
     * @return the state
     */
    public String getState() {
        return state;
    }

    /**
     * @param state
     *            the state to set
     */
    public void setState(String state) {
        this.state = state;
    }

    /**
     * @return the startDate
     */
    public int getStartDate() {
        return startDate;
    }

    /**
     * @param startDate
     *            the startDate to set
     */
    public void setStartDate(int startDate) {
        this.startDate = startDate;
    }

    /**
     * @return the endDate
     */
    public int getEndDate() {
        return endDate;
    }

    /**
     * @param endDate
     *            the endDate to set
     */
    public void setEndDate(int endDate) {
        this.endDate = endDate;
    }
}

CustomTestDeserializer.java

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;

public class CustomTestDeserializer extends StdDeserializer<CustomTest> {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    public CustomTestDeserializer() {
        this(null);
    }

    protected CustomTestDeserializer(Class<?> vc) {
        super(vc);
    }

    @Override
    public CustomTest deserialize(JsonParser jp, DeserializationContext dCtxt)
            throws IOException, JsonProcessingException {
        JsonNode node = jp.getCodec().readTree(jp);
        String state = node.get("state").asText();
        ObjectMapper mapper = new ObjectMapper();
        List<Integer> startDateValue = mapper.convertValue(
                node.get("startDate"), List.class);
        StringBuilder stringBuilder = new StringBuilder();
        for (Integer value : startDateValue) {
            stringBuilder.append(value);
        }
        int startDate = Integer.parseInt(stringBuilder.toString());

        List<Integer> endDateValue = mapper.convertValue(node.get("endDate"),
                List.class);
        stringBuilder.setLength(0);
        for (Integer value : endDateValue) {
            stringBuilder.append(value);
        }
        int endDate = Integer.parseInt(stringBuilder.toString());

        CustomTest customTest = new CustomTest();
        customTest.setEndDate(endDate);
        customTest.setStartDate(startDate);
        customTest.setState(state);
        return customTest;
    }
}

CustomTestClient.java

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;

public class CustomTestClient {
    public static void main(String[] args) {
        String json = "{\"state\" : \"OPEN\", \"startDate\" : [2020, 9, 22], \"endDate\" : [2020, 9, 24]}";

        ObjectMapper mapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        module.addDeserializer(CustomTest.class, new CustomTestDeserializer());
        mapper.registerModule(module);

        try {
            CustomTest customTest = mapper.readValue(json, CustomTest.class);
            System.out.println(customTest.getStartDate() + "   "
                    + customTest.getEndDate() + "   " + customTest.getState());
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }
}

Resultado:

2020922   2020924   OPEN

NOTA: Lembre-se de implementar o tratamento de nulos corretamente.

Assumindo que você não deseja alterar o POJO, portanto, em vez da anotação @JsonDeserialize no nível da classe do bean, é necessário registrar este desserializador personalizado no código do cliente.