如何让杰克逊读到这个无效的JSON?
How to make Jackson read this invalid JSON?
在 Spring 启动应用程序中,使用 Spring Cloud OpenFeign,我正准备读取 Talend 服务器的端点,但我发现这是无效的 JSON (单词 transactions):
周围缺少双引号
{
transactions: [
"some-uuid",
"another-one-uuid",
"and-so-on-uuid"
]
}
我的模型class:
@Data
@SuperBuilder
@NoArgsConstructor
@JsonInclude(JsonInclude.Include.ALWAYS)
public class Transactions {
private List<String> transactions;
}
我的service/clientclass:
@Service
@FeignClient(value = "nativeTalend", url = "http://talend-server:8180/talendmdm/services/rest/")
public interface TalendNativeAPI {
@GetMapping(path = "transactions", produces = MediaType.APPLICATION_JSON_VALUE)
Transactions transactions();
}
注意:它需要@GetMapping 注释中的“produces”,否则服务器会返回 500 HTTP 错误...
这是 OpenFeign 日志:
[TalendNativeAPI#transactions] ---> GET http://talend-server:8180/talendmdm/services/rest/transactions HTTP/1.1
[TalendNativeAPI#transactions] Accept: application/json
[TalendNativeAPI#transactions] Authorization: Basic ==xxx==xxx==xxx==
[TalendNativeAPI#transactions] ---> END HTTP (0-byte body)
[TalendNativeAPI#transactions] <--- HTTP/1.1 200 (282ms)
[TalendNativeAPI#transactions] cache-control: no-cache
[TalendNativeAPI#transactions] content-type: application/json;charset=UTF-8
[TalendNativeAPI#transactions] date: Sun, 27 Sep 2020 13:54:50 GMT
[TalendNativeAPI#transactions] expires: Thu, 01 Jan 1970 00:00:00 GMT
[TalendNativeAPI#transactions] pragma: No-cache
[TalendNativeAPI#transactions] set-cookie: JSESSIONID=XXX_XXX_XXX; Path=/talendmdm; HttpOnly
[TalendNativeAPI#transactions] transfer-encoding: chunked
[TalendNativeAPI#transactions] x-content-type-options: nosniff
[TalendNativeAPI#transactions] x-frame-options: DENY
[TalendNativeAPI#transactions] x-xss-protection: 1; mode=block
[TalendNativeAPI#transactions] <--- END HTTP (17-byte body)
和异常堆栈跟踪(我通过单元测试运行):
feign.codec.DecodeException: Error while extracting response for type [class my.company.app.Transactions] and content type [application/json;charset=UTF-8]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Unexpected character ('t' (code 116)): was expecting double-quote to start field name; nested exception is com.fasterxml.jackson.core.JsonParseException: Unexpected character ('t' (code 116)): was expecting double-quote to start field name
at [Source: (ByteArrayInputStream); line: 1, column: 3]
at feign.SynchronousMethodHandler.decode(SynchronousMethodHandler.java:180)
at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:140)
at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:78)
at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:103)
at com.sun.proxy.$Proxy147.transactions(Unknown Source)
at my.company.app.TalendIntegrationTest.test_noTransactions(TalendIntegrationTest.java:26)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
Caused by: org.springframework.web.client.RestClientException: Error while extracting response for type [class my.company.app.Transactions] and content type [application/json;charset=UTF-8]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Unexpected character ('t' (code 116)): was expecting double-quote to start field name; nested exception is com.fasterxml.jackson.core.JsonParseException: Unexpected character ('t' (code 116)): was expecting double-quote to start field name
at [Source: (ByteArrayInputStream); line: 1, column: 3]
at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:117)
at org.springframework.cloud.openfeign.support.SpringDecoder.decode(SpringDecoder.java:59)
at org.springframework.cloud.openfeign.support.ResponseEntityDecoder.decode(ResponseEntityDecoder.java:62)
at feign.optionals.OptionalDecoder.decode(OptionalDecoder.java:36)
at feign.SynchronousMethodHandler.decode(SynchronousMethodHandler.java:176)
... 36 more
Caused by: org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Unexpected character ('t' (code 116)): was expecting double-quote to start field name; nested exception is com.fasterxml.jackson.core.JsonParseException: Unexpected character ('t' (code 116)): was expecting double-quote to start field name
at [Source: (ByteArrayInputStream); line: 1, column: 3]
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:245)
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.read(AbstractJackson2HttpMessageConverter.java:227)
at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:102)
... 40 more
Caused by: com.fasterxml.jackson.core.JsonParseException: Unexpected character ('t' (code 116)): was expecting double-quote to start field name
at [Source: (ByteArrayInputStream); line: 1, column: 3]
at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:1804)
at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:693)
at com.fasterxml.jackson.core.base.ParserMinimalBase._reportUnexpectedChar(ParserMinimalBase.java:591)
at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._handleOddName(UTF8StreamJsonParser.java:1996)
at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._parseName(UTF8StreamJsonParser.java:1647)
at com.fasterxml.jackson.core.json.UTF8StreamJsonParser.nextToken(UTF8StreamJsonParser.java:733)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:155)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4014)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3085)
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:239)
... 42 more
我如何配置/“修复”Jackson 使其仍然从这个特定的端点读取这个虚假的 JSON(在 Spring Boot + Spring Cloud OpenFeign 的整个上下文中+ Jackson 自动声明的 bean(Spring)?
谢谢。
ALLOW_UNQUOTED_FIELD_NAMES
功能应该可以解决问题:
public class Unquote {
public static void main(String[] args) throws Exception {
ObjectMapper om = new ObjectMapper()
.configure(com.fasterxml.jackson.core.JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
JsonNode tree = om.readTree("{transactions:[\"some.uuid\"]}".getBytes());
System.out.println(tree);
}
}
此答案解释了如何在 Spring 上下文中执行此操作:
Configuring ObjectMapper in Spring
在 Spring 启动应用程序中,使用 Spring Cloud OpenFeign,我正准备读取 Talend 服务器的端点,但我发现这是无效的 JSON (单词 transactions):
周围缺少双引号{
transactions: [
"some-uuid",
"another-one-uuid",
"and-so-on-uuid"
]
}
我的模型class:
@Data
@SuperBuilder
@NoArgsConstructor
@JsonInclude(JsonInclude.Include.ALWAYS)
public class Transactions {
private List<String> transactions;
}
我的service/clientclass:
@Service
@FeignClient(value = "nativeTalend", url = "http://talend-server:8180/talendmdm/services/rest/")
public interface TalendNativeAPI {
@GetMapping(path = "transactions", produces = MediaType.APPLICATION_JSON_VALUE)
Transactions transactions();
}
注意:它需要@GetMapping 注释中的“produces”,否则服务器会返回 500 HTTP 错误...
这是 OpenFeign 日志:
[TalendNativeAPI#transactions] ---> GET http://talend-server:8180/talendmdm/services/rest/transactions HTTP/1.1
[TalendNativeAPI#transactions] Accept: application/json
[TalendNativeAPI#transactions] Authorization: Basic ==xxx==xxx==xxx==
[TalendNativeAPI#transactions] ---> END HTTP (0-byte body)
[TalendNativeAPI#transactions] <--- HTTP/1.1 200 (282ms)
[TalendNativeAPI#transactions] cache-control: no-cache
[TalendNativeAPI#transactions] content-type: application/json;charset=UTF-8
[TalendNativeAPI#transactions] date: Sun, 27 Sep 2020 13:54:50 GMT
[TalendNativeAPI#transactions] expires: Thu, 01 Jan 1970 00:00:00 GMT
[TalendNativeAPI#transactions] pragma: No-cache
[TalendNativeAPI#transactions] set-cookie: JSESSIONID=XXX_XXX_XXX; Path=/talendmdm; HttpOnly
[TalendNativeAPI#transactions] transfer-encoding: chunked
[TalendNativeAPI#transactions] x-content-type-options: nosniff
[TalendNativeAPI#transactions] x-frame-options: DENY
[TalendNativeAPI#transactions] x-xss-protection: 1; mode=block
[TalendNativeAPI#transactions] <--- END HTTP (17-byte body)
和异常堆栈跟踪(我通过单元测试运行):
feign.codec.DecodeException: Error while extracting response for type [class my.company.app.Transactions] and content type [application/json;charset=UTF-8]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Unexpected character ('t' (code 116)): was expecting double-quote to start field name; nested exception is com.fasterxml.jackson.core.JsonParseException: Unexpected character ('t' (code 116)): was expecting double-quote to start field name
at [Source: (ByteArrayInputStream); line: 1, column: 3]
at feign.SynchronousMethodHandler.decode(SynchronousMethodHandler.java:180)
at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:140)
at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:78)
at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:103)
at com.sun.proxy.$Proxy147.transactions(Unknown Source)
at my.company.app.TalendIntegrationTest.test_noTransactions(TalendIntegrationTest.java:26)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
Caused by: org.springframework.web.client.RestClientException: Error while extracting response for type [class my.company.app.Transactions] and content type [application/json;charset=UTF-8]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Unexpected character ('t' (code 116)): was expecting double-quote to start field name; nested exception is com.fasterxml.jackson.core.JsonParseException: Unexpected character ('t' (code 116)): was expecting double-quote to start field name
at [Source: (ByteArrayInputStream); line: 1, column: 3]
at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:117)
at org.springframework.cloud.openfeign.support.SpringDecoder.decode(SpringDecoder.java:59)
at org.springframework.cloud.openfeign.support.ResponseEntityDecoder.decode(ResponseEntityDecoder.java:62)
at feign.optionals.OptionalDecoder.decode(OptionalDecoder.java:36)
at feign.SynchronousMethodHandler.decode(SynchronousMethodHandler.java:176)
... 36 more
Caused by: org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Unexpected character ('t' (code 116)): was expecting double-quote to start field name; nested exception is com.fasterxml.jackson.core.JsonParseException: Unexpected character ('t' (code 116)): was expecting double-quote to start field name
at [Source: (ByteArrayInputStream); line: 1, column: 3]
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:245)
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.read(AbstractJackson2HttpMessageConverter.java:227)
at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:102)
... 40 more
Caused by: com.fasterxml.jackson.core.JsonParseException: Unexpected character ('t' (code 116)): was expecting double-quote to start field name
at [Source: (ByteArrayInputStream); line: 1, column: 3]
at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:1804)
at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:693)
at com.fasterxml.jackson.core.base.ParserMinimalBase._reportUnexpectedChar(ParserMinimalBase.java:591)
at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._handleOddName(UTF8StreamJsonParser.java:1996)
at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._parseName(UTF8StreamJsonParser.java:1647)
at com.fasterxml.jackson.core.json.UTF8StreamJsonParser.nextToken(UTF8StreamJsonParser.java:733)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:155)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4014)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3085)
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:239)
... 42 more
我如何配置/“修复”Jackson 使其仍然从这个特定的端点读取这个虚假的 JSON(在 Spring Boot + Spring Cloud OpenFeign 的整个上下文中+ Jackson 自动声明的 bean(Spring)?
谢谢。
ALLOW_UNQUOTED_FIELD_NAMES
功能应该可以解决问题:
public class Unquote {
public static void main(String[] args) throws Exception {
ObjectMapper om = new ObjectMapper()
.configure(com.fasterxml.jackson.core.JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
JsonNode tree = om.readTree("{transactions:[\"some.uuid\"]}".getBytes());
System.out.println(tree);
}
}
此答案解释了如何在 Spring 上下文中执行此操作: Configuring ObjectMapper in Spring