[英]Converting ZonedDateTime type to Gson
I have rest service that return arraylist of object,and I have implemented jersy restful client to execute it,but I have problem in converting ZonedDateTime type to json so I get this error我有返回对象数组列表的休息服务,并且我已经实现了 jersy restful 客户端来执行它,但是我在将 ZonedDateTime 类型转换为 json 时遇到了问题,所以我收到了这个错误
Caused by: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 231 path $[0].lastmodifieddate
How can i fix this problem?我该如何解决这个问题?
lastmodifieddate column in entity实体中的上次修改日期列
@Column(name = "lastmodifieddate")
private ZonedDateTime lastmodifieddate;
//getter and setter
rest service休息服务
@RequestMapping(value = "/getScoreFactor",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
@Timed
public List<Scorefactor> getScoreFactor() throws JSONException {
return scoreService.getScoreFactor();
}
jersy restful client jersy 宁静的客户
try {
Client client = Client.create();
WebResource webResource = client
.resource("http://localhost:8080/adap/api/getScoreFactor");
ClientResponse response = webResource.accept("application/json")
.get(ClientResponse.class);
String output = response.getEntity(String.class);
System.out.println("output--"+output);
Type listType = new TypeToken<List<Scorefactor>>() {}.getType();
List<Scorefactor> scorefactors = new Gson().fromJson(output,listType);
System.out.println(scorefactors);
} catch (Exception e) {
e.printStackTrace();
}
public static final Gson GSON = new GsonBuilder()
.registerTypeAdapter(ZonedDateTime.class, new TypeAdapter<ZonedDateTime>() {
@Override
public void write(JsonWriter out, ZonedDateTime value) throws IOException {
out.value(value.toString());
}
@Override
public ZonedDateTime read(JsonReader in) throws IOException {
return ZonedDateTime.parse(in.nextString());
}
})
.enableComplexMapKeySerialization()
.create();
There are at least two ways to achieve this:至少有两种方法可以实现这一点:
Little changes within your code:代码中的小改动:
Type listType = new TypeToken<List<Scorefactor>>() {}.getType();
List<Scorefactor> scorefactors = new GsonBuilder()
.registerTypeAdapter(ZonedDateTime.class, GsonHelper.ZDT_DESERIALIZER)
.create()
.fromJson(output, listType);
Helper Class助手类
class GsonHelper {
public static final JsonDeserializer<ZonedDateTime> ZDT_DESERIALIZER = new JsonDeserializer<ZonedDateTime>() {
@Override
public ZonedDateTime deserialize(final JsonElement json, final Type typeOfT, final JsonDeserializationContext context) throws JsonParseException {
JsonPrimitive jsonPrimitive = json.getAsJsonPrimitive();
try {
// if provided as String - '2011-12-03T10:15:30+01:00[Europe/Paris]'
if(jsonPrimitive.isString()){
return ZonedDateTime.parse(jsonPrimitive.getAsString(), DateTimeFormatter.ISO_ZONED_DATE_TIME);
}
// if provided as Long
if(jsonPrimitive.isNumber()){
return ZonedDateTime.ofInstant(Instant.ofEpochMilli(jsonPrimitive.getAsLong()), ZoneId.systemDefault());
}
} catch(RuntimeException e){
throw new JsonParseException("Unable to parse ZonedDateTime", e);
}
throw new JsonParseException("Unable to parse ZonedDateTime");
}
};
}
Changes for your Client implementation:客户端实现的更改:
ClientConfig config = new DefaultClientConfig();
config.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
Client client = Client.create(config);
List<Scorefactor> result = client.resource("http://localhost:8080/adap/api/getScoreFactor"")
.accept("application/json")
.get(ClientResponse.class)
.getEntity(new GenericType<List<Scorefactor>>(){});
System.out.println(result);
You might need to import jersey-json for this您可能需要为此导入 jersey-json
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-bundle</artifactId>
<version>1.19.1</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-json</artifactId>
<version>1.19.1</version>
</dependency>
Btw, why do you use 1.*?顺便说一句,你为什么使用 1.*?
Your Scorefactor你的计分器
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Scorefactor implements Serializable {
@Column(name = "lastmodifieddate")
@XmlElement(name = "lastmodifieddate")
@XmlJavaTypeAdapter(ZonedDateTimeToStringXmlAdapter.class)
private ZonedDateTime lastmodifieddate;
//...
ZonedDateTime from / to String (recommended) ZonedDateTime from / to String (推荐)
public class ZonedDateTimeToStringXmlAdapter extends XmlAdapter<String, ZonedDateTime> {
@Override
public ZonedDateTime unmarshal(final String v) throws DateTimeParseException {
return ZonedDateTime.parse(v);
}
@Override
public String marshal(final ZonedDateTime v) throws Exception {
return v.toString();
}
}
ZonedDateTime from / to Long ZonedDateTime from / to Long
public class ZonedDateTimeToLongXmlAdapter extends XmlAdapter<Long, ZonedDateTime> {
@Override
public ZonedDateTime unmarshal(final Long v) throws DateTimeParseException {
return ZonedDateTime.ofInstant(Instant.ofEpochMilli(v.longValue()), ZoneId.systemDefault());
}
@Override
public Long marshal(final ZonedDateTime v) throws Exception {
return Long.valueOf(v.toInstant().toEpochMilli());
}
}
You could also build your own MessageBodyReader/MessageBodyWriter or use other implementations like Moxy.您还可以构建自己的 MessageBodyReader/MessageBodyWriter 或使用其他实现,如 Moxy。
I would like to recommend to use Jersey 2.*.我想推荐使用 Jersey 2.*。
Hope this was helpful somehow.希望这在某种程度上有所帮助。 Have a nice day.有一个美好的一天。
I have fixed it,This is the code after updates我已经修复了,这是更新后的代码
Client client = Client.create();
WebResource webResource = client
.resource("http://localhost:8080/adap/api/getScoreFactor");
ClientResponse response = webResource.accept("application/json")
.get(ClientResponse.class);
String output = response.getEntity(String.class);
Gson gson = new GsonBuilder().registerTypeAdapter(ZonedDateTime.class, new JsonDeserializer<ZonedDateTime>() {
@Override
public ZonedDateTime deserialize(JsonElement json, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
return ZonedDateTime.parse(json.getAsJsonPrimitive().getAsString());
}
}).create();
Type listType = new TypeToken<List<Scorefactor>>() {}.getType();
List<Scorefactor> scorefactors = gson.fromJson(output,listType);
Your solution posted doesn't work because ZonedDateTime's Json serialization is not a Json primitive but a Json object that contains more than a single element.您发布的解决方案不起作用,因为 ZonedDateTime 的 Json 序列化不是 Json 原语,而是包含多个元素的 Json 对象。 It needs to develop a bit and here is a completed solution:它需要发展一点,这是一个完整的解决方案:
public Gson gson() {
return new GsonBuilder().registerTypeAdapter(ZonedDateTime.class, new JsonDeserializer<ZonedDateTime>() {
@Override
public ZonedDateTime deserialize(JsonElement json, Type type,
JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
JsonObject jsonObj = json.getAsJsonObject();
JsonObject dateTime = jsonObj.getAsJsonObject("dateTime");
JsonObject date = dateTime.getAsJsonObject("date");
int year = date.get("year").getAsInt();
int month = date.get("month").getAsInt();
int day = date.get("day").getAsInt();
JsonObject time = dateTime.getAsJsonObject("time");
int hour = time.get("hour").getAsInt();
int minute = time.get("minute").getAsInt();
int second = time.get("second").getAsInt();
int nano = time.get("nano").getAsInt();
JsonObject zone = jsonObj.getAsJsonObject("zone");
String id = zone.get("id").getAsString();
return ZonedDateTime.of(year, month, day, hour, minute, second, nano, ZoneId.of(id));
}
}).create();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.