目前我正在开发两个项目:一个是使用Java 1.5和Spring 3.2.3,另一个是使用Java 1.8和Spring 4.1.5。您可能知道,因为Spring 4.x.x默认HttpMessageConverter
是Gson。在版本4.x.x之前,默认是杰克逊。我认为这不会影响兼容性,但是请注意:它确实......具体来说,我在谈论java.util.Date
解析/映射。
假设我有一个如下课程(equals()
和hashCode()
方法被忽略):
public class FooBar {
public String str = getRandomStringEncodedInUTF8();
public Date date = new Date(0); //1970-01-01 00:00:00
}
public void retrieveFooBars() {
Type collectionType = new TypeToken<HashSet<FooBar>>(){}.getType();
Gson gson = new GsonBuilder().
registerTypeAdapter(FooBar.class, new FooBarDeserializer()).create();
String ipAddress = getIpAddress();
RestTemplate request = new RestTemplate();
String gsonString;
try {
gsonString = request.getForObject("http://"
+ ipAddress+ ":8080/foobars/get", String.class);
} catch (Exception e) {
return;
}
Set<FooBar> fooBars = gson.fromJson(gsonString, collectionType);
}
FooBarDeserializer
如下:
public class FooBarDeserializer implements JsonDeserializer<FooBar> {
private final DateTimeFormatter dateFormatter = DateTimeFormat
.forPattern("yyyy-MM-dd");
@Override
public FooBar deserialize(JsonElement element, Type type,
JsonDeserializationContext context) throws JsonParseException {
FooBar fooBar = new FooBar();
JsonObject obj = element.getAsJsonObject();
JsonElement str = obj.get("str");
if (str != null)
if (!str.isJsonNull()) {
fooBar.str = originalId.getAsString();
}
JsonElement date = obj.get("date");
if (date != null)
if (!date.isJsonNull()) {
String temp = date.getAsString();
if (temp != null) {
fooBar.date = dateFormatter.parseDateTime(temp).toDate();
}
}
return FooBar;
}
}
如果我不使用FooBarDeserializer
,我会得到com.google.gson.JsonSyntaxException: 1970-01-01
:java.text.ParseException: Unparseable date: "1970-01-01"
到目前为止一直很好。我可以接收数据,并保留我的UTF-8编码。
使用旧版本的Spring向服务器发送数据时出现问题:
public void distributeFooBars() {
Gson gson = new GsonBuilder()
.registerTypeAdapter(FooBar.class, new FooBarSerializer()).create();
String ipAddress = getIpAddress();
Set<FooBar> newFooBars = getNewFooBars();
RestTemplate request = new RestTemplate();
String gsonString = gson.toJson(newFooBars);
try {
request.postForObject("http://" + ipAddress + ":8080/foobars/set",
gsonString, Boolean.class);
} catch (Exception e) {
return;
}
}
如果我在将newFooBars发送到“旧”服务器之前没有使用显式Gson,并让GsonHttpMessageConverter
执行它的工作,我保留我的UTF-8字符串,但解析日期失败,因为它写为“1970年1月1日”。如果我在发送之前明确使用Gson并将newFooBars转换为String,我会丢失UTF-8字符(即代替ČĆĐŠŽ_čćđšž我会收到????? _ ?????)但解析日期不会丢失一个例外。客户序列化器是:
public class FooBarSerializer implements JsonSerializer<FooBar> {
private final DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd");
@Override
public JsonElement serialize(FooBar fooBar, Type type,
JsonSerializationContext context) {
JsonObject obj = new JsonObject();
obj.addProperty("str", fooBar.str);
String date = null;
if (fooBar.date != null) {
date = formatter.print(fooBar.date.getTime());
}
obj.addProperty("date", date);
return obj;
}
}
SIDE注意:如果显式使用Gson,则在较旧的服务器控制器上具有以下映射:
@RequestMapping(value = "/set", method = RequestMethod.POST, consumes="text/plain;charset=UTF-8")
否则就是:
@RequestMapping(value = "/set", method = RequestMethod.POST, consumes="application/json;charset=UTF-8")
否则我得到415不支持的媒体类型。
我知道这是一篇很长的帖子,但我会感激任何可以帮助我的人。所以我的问题是:
有没有办法解决这个问题?就像有一个系统范围的Gson序列化器,但仅适用于java.util.Date
。或者设置强制UTF-8编码为普通/文本?
答案 0 :(得分:2)
从我的构建路径中排除gson-2.3.1.jar
后,Jackson2HttpMessageConverter
成为默认值。 Gson是普通代码段的依赖项,因此在pom.xml中我添加了:
<dependency>
<groupId>com.example</groupId>
<artifactId>common_code</artifactId>
<version>6.9</version>
<exclusions>
<exclusion>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</exclusion>
</exclusions>
</dependency>
之后,问题不是Date
个对象而是joda DateTime
个对象。添加jackson-datatype-joda
作为maven依赖项解决了该问题:
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-joda</artifactId>
<version>${jackson.version}</version>
</dependency>
现在一切都按预期工作了...... Sotirios Delimanolis感谢您的帮助。
答案 1 :(得分:0)
我知道有两种方法可以解决此问题(自GSON 2.8.2起):
1告诉GSON使用哪种模式:
Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd").create();
2仅为类型Date
创建一个新的DateSerializer:
public class DateDeserializer implements JsonDeserializer<Date> {
@Override
public Date deserialize(JsonElement element, Type arg1, JsonDeserializationContext arg2) {
// Do your stuff here...
String dateString = element.getAsString();
Long val = Long.valueOf(dateString);
Timestamp timestamp = new Timestamp(val);
Date date = new Date(timestamp.getTime());
return date;
}
}
并使用它:
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Date.class, new DateDeserializer());
这解决了我的问题,没有排除任何问题。