我有一个用Java编写的Spring Boot和Spring MVC应用程序,它响应带有包含字节数组的对象的get请求:
public HashedPasswordSpec get() {
User user = userRepository.findByEmail("example@example.com");
return user.getHashedPasswordSpec();
}
在客户端我尝试使用相同的类自动反序列化它:
RestTemplate restTemplate = new RestTemplate();
HashedPasswordSpec spec = restTemplate.getForObject("http://localhost:8080/v1/hashed-password-spec", HashedPasswordSpec.class);
失败并出现此错误:
Caused by: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was STRING at line 1 column 10 path $.salt
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:224)
at com.google.gson.Gson.fromJson(Gson.java:887)
at com.google.gson.Gson.fromJson(Gson.java:852)
at org.springframework.http.converter.json.GsonHttpMessageConverter.readTypeToken(GsonHttpMessageConverter.java:161)
... 39 more
Caused by: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was STRING at line 1 column 10 path $.salt
at com.google.gson.stream.JsonReader.beginArray(JsonReader.java:350)
at com.google.gson.internal.bind.ArrayTypeAdapter.read(ArrayTypeAdapter.java:70)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:129)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:220)
... 42 more
salt
是byte[]
。当我得到一个字符串并将其打印出来时:
String spec = restTemplate.getForObject("http://localhost:8080/v1/hashed-password-spec", String.class);
System.out.println(spec);
我明白这一点:
{"salt":"2GKm9SVxsvLmwaydk8heK/eB94HoPR21+2rTmKMjWo0=","algorithm":"SCrypt","cost":12,"blockSize":8,"parallelization":1,"keyLength":256}
正如您所看到的,salt被序列化为Base64,但这并不是Gson开箱即用的字节数组。 Spring Boot是否扩展Gson以将字节数组序列化为Base64字符串?如果是这样,RestTemplate是否省略了这个扩展名?它们彼此不兼容吗?我在这里缺少什么?
答案 0 :(得分:1)
默认情况下,RestTemplate
和Spring MVC's infrastructure都会注册各种序列化程序/反序列化程序,具体取决于它们在类路径中找到的内容。
具体来说,他们正在寻找杰克逊和Gson的JSON序列化,如果发现它们,他们都更喜欢杰克逊。
在您的情况下,您的服务器将byte[]
序列化为Base64字符串这一事实暗示它正在使用Jackson,因为这是其默认策略(请参阅ByteArraySerializer
)。
我们可以从您的错误日志中看到RestTemplate
无法使用Gson
解析JSON。对于类型为Gson
的字段,byte[]
不使用或期望Base64字符串,它只需要一个包含数字的JSON数组。
因此,您的客户端未将Jackson注册为序列化程序,因为它不在类路径中,或者因为您已注册了不包含Jackson变体的HttpMessageConverter
个实例的自定义列表。