来自RESTful请求的JSON解析异常

3

我的应用程序向外部来源发出RESTful服务请求。 外部来源返回JSON数据。 但是,我遇到了以下异常:

"com.fasterxml.jackson.databind.JsonMappingException: Invalid UTF-8 start byte 0xa0."

我的Java代码如下,用于进行RESTful请求:

`
HttpSession httpSession = new HttpSession();
httpSession.createHeaders();
httpSession.setupMessageConverters();
restTemplate.setMessageConverters(httpSession.getMessageConverterList());
ResponseEntity<JsonData> responseEntity = restTemplate.exchange(URLConstants.GET_CUSTOM_EVENTS, HttpMethod.GET, httpSession.getHttpEntity(), JsonData.class);

我有一些控制HTTP头和反序列化设置的代码,如下:

public void createHeaders(){
    HttpHeaders httpHeaders = new HttpHeaders(); 
    httpHeaders.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));

    HttpEntity<String> httpEntity = new HttpEntity<String>(httpHeaders);
    this.httpEntity = httpEntity;

    this.httpHeaders = httpHeaders;
}      

public void setupMessageConverters(){
    List<HttpMessageConverter<?>> messageConverterList = new ArrayList<>();
    MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
    messageConverter.setObjectMapper(objectMapper);
    messageConverterList.add(messageConverter);

    this.messageConverterList = messageConverterList;
}

出现错误的JSON行是这个(在此Web方法的Swagger UI中可见):

{
    "object_id": 5,
    "web_method_rest1": " /rest/information/5",
    "custom_event_type": "save"
}

似乎编码/解码并不喜欢在JSON数据值中存在前导空格。堆栈跟踪显示引起错误的JSON变量是web_method_rest1。是否有一种改变JSON数据编码方式的方法,使得允许前导空格,例如反序列化设置或我可以添加到HTTP标头的某些内容?因为JSON数据来自外部源,我无法轻松控制那些数据。
如果您能提供任何帮助,即使有一些我可以查询的文档,我也将不胜感激。
以下是更完整的堆栈跟踪信息:
org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON document: Invalid UTF-8 start byte 0xa0
 at [Source: java.io.PushbackInputStream@84240f; line: 8, column: 31]
 at [Source: java.io.PushbackInputStream@84240f; line: 8, column: 29] (through reference chain: com.foo.bar.webclient.model.rest.JsonData["CustomEvents"]->com.foo.bar.webclient.model.rest.CustomEventResult["CustomEvent"]->java.util.ArrayList[0]->com.foo.bar.webclient.model.rest.CustomEvent["web_method_rest1"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Invalid UTF-8 start byte 0xa0
 at [Source: java.io.PushbackInputStream@84240f; line: 8, column: 31]
 at [Source: java.io.PushbackInputStream@84240f; line: 8, column: 29] (through reference chain: com.foo.bar.webclient.model.rest.JsonData["CustomEvents"]->com.foo.bar.webclient.model.rest.CustomEventResult["CustomEvent"]->java.util.ArrayList[0]->com.foo.bar.webclient.model.rest.CustomEvent["web_method_rest1"])
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:234)
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.read(AbstractJackson2HttpMessageConverter.java:219)
    at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:95)
    at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:917)
    at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:901)
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:655)
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:613)
    at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:531)
    at com.foo.bar.webclient.rest.clients.RestfulRequests.getCustomEvents(RestfulRequests.java:58)
    at com.foo.bar.webclient.rest.clients.RestfulRequests$$FastClassBySpringCGLIB$$a04c852c.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:738)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
    at org.springframework.retry.interceptor.RetryOperationsInterceptor$1.doWithRetry(RetryOperationsInterceptor.java:91)
    at org.springframework.retry.support.RetryTemplate.doExecute(RetryTemplate.java:286)
    at org.springframework.retry.support.RetryTemplate.execute(RetryTemplate.java:163)
    at org.springframework.retry.interceptor.RetryOperationsInterceptor.invoke(RetryOperationsInterceptor.java:118)
    at org.springframework.retry.annotation.AnnotationAwareRetryOperationsInterceptor.invoke(AnnotationAwareRetryOperationsInterceptor.java:152)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:673)
    at com.foo.bar.webclient.rest.clients.RestfulRequests$$EnhancerBySpringCGLIB$$d3b75a44.getCustomEvents(<generated>)
    at com.foo.bar.webclient.batch.CustomEventReader.read(CustomEventReader.java:30)
    at com.foo.bar.webclient.batch.CustomEventReader.read(CustomEventReader.java:1)
    at org.springframework.batch.core.step.item.SimpleChunkProvider.doRead(SimpleChunkProvider.java:91)
    at org.springframework.batch.core.step.item.FaultTolerantChunkProvider.read(FaultTolerantChunkProvider.java:87)
    at org.springframework.batch.core.step.item.SimpleChunkProvider$1.doInIteration(SimpleChunkProvider.java:116)
    at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:374)
    at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215)
    at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:144)
    at org.springframework.batch.core.step.item.SimpleChunkProvider.provide(SimpleChunkProvider.java:110)
    at org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:69)
    at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:406)
    at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:330)
    at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133)
    at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:271)
    at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:81)
    at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:374)
    at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215)
    at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:144)
    at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:257)
    at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:200)
    at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:148)
    at org.springframework.batch.core.job.AbstractJob.handleStep(AbstractJob.java:392)
    at org.springframework.batch.core.job.SimpleJob.doExecute(SimpleJob.java:135)
    at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:306)
    at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:135)
    at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50)
    at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:128)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
    at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:127)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
    at com.sun.proxy.$Proxy67.run(Unknown Source)
    at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.execute(JobLauncherCommandLineRunner.java:214)
    at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.executeLocalJobs(JobLauncherCommandLineRunner.java:231)
    at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.launchJobFromProperties(JobLauncherCommandLineRunner.java:123)
    at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.run(JobLauncherCommandLineRunner.java:117)
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:776)
    at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:760)
    at org.springframework.boot.SpringApplication.afterRefresh(SpringApplication.java:747)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1162)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1151)
    at com.foo.bar.webclient.MyApplication.main(MyApplication.java:10)
Caused by: com.fasterxml.jackson.databind.JsonMappingException: Invalid UTF-8 start byte 0xa0
 at [Source: java.io.PushbackInputStream@84240f; line: 8, column: 31]
 at [Source: java.io.PushbackInputStream@84240f; line: 8, column: 29] (through reference chain: com.foo.bar.webclient.model.rest.JsonData["CustomEvents"]->com.foo.bar.webclient.model.rest.CustomEventResult["CustomEvent"]->java.util.ArrayList[0]->com.foo.bar.webclient.model.rest.CustomEvent["web_method_rest1"])
    at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:388)
    at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:348)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.wrapAndThrow(BeanDeserializerBase.java:1600)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:278)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:140)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:287)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:259)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:26)
    at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:504)
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:104)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:276)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:140)
    at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:504)
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:104)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:276)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:140)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3798)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2922)
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:231)
    ... 69 common frames omitted
Caused by: com.fasterxml.jackson.core.JsonParseException: Invalid UTF-8 start byte 0xa0
 at [Source: java.io.PushbackInputStream@84240f; line: 8, column: 31]
    at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:1702)
    at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:558)
    at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._reportInvalidInitial(UTF8StreamJsonParser.java:3544)
    at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._reportInvalidChar(UTF8StreamJsonParser.java:3538)
    at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._finishString2(UTF8StreamJsonParser.java:2543)
    at com.fasterxml.jackson.core.json.UTF8StreamJsonParser._finishAndReturnString(UTF8StreamJsonParser.java:2469)
    at com.fasterxml.jackson.core.json.UTF8StreamJsonParser.getText(UTF8StreamJsonParser.java:315)
    at com.fasterxml.jackson.databind.deser.std.StringDeserializer.deserialize(StringDeserializer.java:36)
    at com.fasterxml.jackson.databind.deser.std.StringDeserializer.deserialize(StringDeserializer.java:11)
    at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:504)
    at com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:111)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:276)
    ... 84 common frames omitted
2个回答

3
尝试在标题中设置内容类型和字符集,类似于这样的"Content-Type","application/json;charset=UTF-8"。

1
你能否发布更多关于该问题的堆栈跟踪信息?是否有任何预处理外部输入以删除此问题字符的方法?
0xa0不是空格,因此它不会像标准空格一样被处理,这可能导致问题。如果可以在使用之前预处理数据,则可以使用replace()函数将有问题的字符替换为空格以消除问题。
    string = string.replace('\u00A0',' ')

此外,请确保在数据编码方面使用正确的类型/格式。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接