【发布时间】:2015-03-18 16:20:34
【问题描述】:
目前我在做两个项目:一个是使用 Java 1.5 和 Spring 3.2.3,另一个是使用 Java 1.8 和 Spring 4.1.5。您可能知道,由于 Spring 4.x.x 默认 HttpMessageConverter 是 Gson。在 4.x.x 版本之前默认是 Jackson。我认为这不会影响兼容性,但你瞧:它确实...具体来说,我在谈论 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 字符串,但解析日期失败,因为它被写为“jan 1, 1970”。如果我在发送之前明确使用 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;
}
}
旁注:如果显式使用 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 Unsupported media type。
我知道这是一篇很长的帖子,但我会感谢任何可以帮助我的人。所以我的问题是:
有没有办法解决这个问题?就像拥有一个系统范围的 Gson 序列化器,但仅适用于 java.util.Date。或者设置强制对纯文本/文本进行 UTF-8 编码?
【问题讨论】:
-
Jackson 在 Spring 4 中仍然是首选。至少如果你使用默认的
@EnableWebMvc配置是这样。 -
@SotiriosDelimanolis 你能详细说明一下吗?我的项目中有 spring-webmvc 作为 maven 依赖项。另外,我的 servlet.xml 文件中有
标记。但是,我仍然得到 RestTemplate:770 - Writing [[FooBar [str=ČĆĐŠŽ_čćđšž, date=... using ... GsonHttpMessageConverter -
可能与您的问题无关,但如果 Jackson 在您的类路径中,则无论 Gson 是否在您的类路径中,都会注册 Jackson
HttpMessageConverter。如果 Jackson 不是而 Gson 是,则 GsonHttpMessageConverter将被注册。 -
我两个都有:
jackson-core-2.5.1和gson-2.3.1。有没有办法强制JacksonHttpMessageConverter超过 Gson?
标签: java spring utf-8 jackson gson