无法读取文档:无法从 START_OBJECT 令牌中反序列化 java.lang.String 的实例

Posted

技术标签:

【中文标题】无法读取文档:无法从 START_OBJECT 令牌中反序列化 java.lang.String 的实例【英文标题】:Could not read document: Can not deserialize instance of java.lang.String out of START_OBJECT token 【发布时间】:2022-01-02 17:27:46 【问题描述】:

我正在通过 POSTMAN 对我的 POST 方法进行调用,该方法应该返回一个 String 类型,但是当我进行调用时,它给了我错误 "Could not read document: Can not deserialize instance of java. lang.String out of START_OBJECT token"。为什么会这样?

实体中的属性:

@Column(name = "CIF_NIF")
@JsonView(Views.Buscador.class)
@JsonProperty("cifNif")
private String cifNif;

RestController

@PostMapping(value = "/recuperaNombreLegalCliente")
public String recuperaNombreLegalCliente(@RequestBody String cifNif) 
  return contratoService.getNombreLegalCliente(cifNif);

存储库

@Query(value="SELECT c.nombreSociedadPersona FROM Contrato c WHERE c.cifNif= ?1")
public String getNombreLegalCliente(String cifNif);

我在进行方法调用时的输入:


    "cifNif": "E85882355"

现在编辑 1 堆栈跟踪错误(@sigur 回答后)

org.springframework.dao.InvalidDataAccessApiUsageException: Parameter value [Contrato [id=null, tipoSolicitud=null, tipoContratoDiscriminator=null, cifNif=E85882355] did not match expected type [java.lang.String (n/a)]; nested exception is java.lang.IllegalArgumentException: Parameter value [Contrato [id=null, tipoSolicitud=null, tipoContratoDiscriminator=null, cifNif=E85882355] did not match expected type [java.lang.String (n/a)]
    at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:384)
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:246)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:491)
    at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59)
    at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:147)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:119)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
    at com.sun.proxy.$Proxy174.getNombreLegalCliente(Unknown Source)
    at com.xxx.xxxx.servicio.ContratoService.getNombreLegalCliente(ContratoService.java:24)
    at com.xxxx.xxxx.acciones.rest.SolicitudAutorizacionPreciosRestController.recuperaNombreLegalCliente(SolicitudAutorizacionPreciosRestController.java:56)

【问题讨论】:

更新了答案,但如果您需要更多支持,您应该打开另一个问题,因为原来的问题看起来已经解决了@okjfokjrf 【参考方案1】:

@RequestBody 的映射器正在尝试读取您的输入并将其数据转换为请求的类型/对象。

在您的情况下,它正在尝试将您的 json 文本转换为 String。默认情况下不允许这样做,您应该更改反映 json 输入模型的 POJO 类中的输入。

public String recuperaNombreLegalCliente(@RequestBody String cifNif) 更改为String recuperaNombreLegalCliente(@RequestBody Cliente cifNif),其中Cliente 是这样的类:

 class Cliente 
   private String cifNif;

  public void setCifNif(String cifNif) this.cifNif = cifNif;
  public String getCifNif() return cifNif;
 

案例编辑 1 -> org.springframework.dao.InvalidDataAccessApiUsageException

该错误与存储库中的查询生成有关。当您将String 更改为Cliente 类时,您还需要为您的存储库或查询提供足够的调用;因为现在您正尝试将 Cliente 实例作为参数映射到字符串字段/列的查询中。

如果您想使用Cliente,您需要在查询中使用cifNif 属性。示例:

@Query(value="SELECT c.nombreSociedadPersona FROM Contrato c WHERE c.cifNif=cliente.cifNif")
public String getNombreLegalCliente(@Param("cliente") Cliente cliente);
...

或者,如果您想使用字符串值,只需从控制器调用存储库函数:

String recuperaNombreLegalCliente(@RequestBody Cliente cifNif) 
 repository.getNombreLegalCliente(cifNif.getCifNif());
...

存储库方法在哪里:

@Query(value="SELECT c.nombreSociedadPersona FROM Contrato c WHERE c.cifNif= ?1")
public String getNombreLegalCliente(String cifNif);
...

【讨论】:

那么我应该输入类似 "cliente" : "cifNif" : "xxxx" 的内容? Request 将是相同的,但是当映射器将其数据反映到您的模型中时,它使用 getter 和 setter POJO 样式。因此,当请求 "cifNif": "E85882355" 将“进入”您的控制器时,映射器和 @RequestBody 将转换为 Cliente。他们从您的 json 中提取字段(在您的情况下只有 cifNif),并将它们找到 Cliente 类(通过“pojo setter”样式 -> setCiNif)。 在相同的输入和您的更改下无法为我工作原因:java.lang.IllegalArgumentException:参数值 [Contrato [id=null,tipoSolicitud=null,tipoContratoDiscriminator=null,cifNif= E85882355] 您应该为该案例添加堆栈跟踪,因为我怀疑错误不再是“无法读取文档:无法将 java.lang.String 实例反序列化出 START_OBJECT 令牌”所以它已经改变了,因为现在看起来你比以前更进一步。 是的,这不是同一个错误,我在问题中添加了轨迹跟踪错误

以上是关于无法读取文档:无法从 START_OBJECT 令牌中反序列化 java.lang.String 的实例的主要内容,如果未能解决你的问题,请参考以下文章

JSON 解析错误:无法从 START_OBJECT 令牌中反序列化 `byte[]` 的实例

无法从 START_OBJECT 令牌中反序列化 `java.lang.Boolean` 的实例

无法从 START_OBJECT 令牌中反序列化 java.util.ArrayList 的实例

JSON 解析错误:无法从 START_OBJECT 令牌中反序列化 java.util.ArrayList 的实例

com.fasterxml.jackson.databind.exc.MismatchedInputException:无法从 START_OBJECT 令牌中反序列化 `java.util.Arra

无法从 START_OBJECT 令牌中反序列化 `java.lang.Long` 的实例;在 Spring Boot 帖子上