从 json 中读取日期作为数组整数,并作为整数与 POJO 映射
Read date as an array integer from json and map with POJO as an integer
我正在从 rest api 获取 json 并且我想将数据存储在 POJO 列表中。下面是相同的代码:
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;
}
从rest获取字符串的方法api:
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);
}
下面是我的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"
} ]
}
前提是我不能修改现有的 POJO(除非需要),因为它需要大量修改。
我很困惑如何从数组访问日期并将其映射到 startDate 具有整数数据类型的 POJO。
能否在POJO中定义一个@JsonCreator注解的构造器,然后在json中解析List获取日期字段?
与此类似。
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();
}
}
}
输出:
2020922 2020924 OPEN
如果无法更新 POJO class,则还有另一种实现自定义反序列化程序的替代方法。在哪里可以实现类似的转换逻辑。
自定义反序列化方法
自定义Test.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();
}
}
}
输出:
2020922 2020924 OPEN
注意:请记住正确执行空值处理。
假设您不想更改 POJO,而不是 bean class 级别的 @JsonDeserialize 注释,需要在客户端代码中注册此自定义反序列化器。
我正在从 rest api 获取 json 并且我想将数据存储在 POJO 列表中。下面是相同的代码:
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;
}
从rest获取字符串的方法api:
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);
}
下面是我的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"
} ]
}
前提是我不能修改现有的 POJO(除非需要),因为它需要大量修改。 我很困惑如何从数组访问日期并将其映射到 startDate 具有整数数据类型的 POJO。
能否在POJO中定义一个@JsonCreator注解的构造器,然后在json中解析List获取日期字段?
与此类似。
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();
}
}
}
输出:
2020922 2020924 OPEN
如果无法更新 POJO class,则还有另一种实现自定义反序列化程序的替代方法。在哪里可以实现类似的转换逻辑。
自定义反序列化方法
自定义Test.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();
}
}
}
输出:
2020922 2020924 OPEN
注意:请记住正确执行空值处理。
假设您不想更改 POJO,而不是 bean class 级别的 @JsonDeserialize 注释,需要在客户端代码中注册此自定义反序列化器。