当前位置: 首页 > 知识库问答 >
问题:

无法将convert JSON数组传递给spring控制器中的对象列表

司空繁
2023-03-14

我试图实现一个场景,希望能够将JSON对象数组作为请求体发送到Spring MVC控制器。

  1. 使用@ResponseBody自定义HttpMessageConverter来执行Json操作
  2. 如何摆脱
  3. http://prasanthnath.wordpress.com/2013/08/23/type-conversion-in-spring/#more-199
  4. http://gerrydevstory.com/2013/08/14/posting-json-to-spring-mvc-controller/
  5. 当Accept标头为*/*时使用@ResponseBody返回Spring json
  6. 抛出HttpMediaTypeNotAcceptableException

但这些建议没有一个奏效。如果我错过了其他的帖子,我向你道歉。

    null
@RequestMapping("/config")
public class ConfigController {

  @Autowired
  private final Service service;

   // This works. I don't know why.
   @RequestMapping("/fetch", method=RequestMethod.GET)
   @ResponseBody
   @ResponseStatus(HttpStatus.OK)
   public String readConfigProperties() throws Exception {
     ImmutableList<Config> configObjects = this.service.readConfiguration();
     return configObjects;
   }
}

更新:我在这篇文章的前一个版本中使用了@ResponseBody注释。我将帖子改为使用@RequestBody,但没有影响。

@RequestMapping(method=RequestMethod.POST, consumes={"application/json"}, value="/update}
@ResponseStatus(HttpStatus.OK)
public void updateConfig(@RequestBody List<Config> configList) throws Exception {
  this.service.updateConfiguration(configList);

}

在本例中,configList是LinkedHashMap对象的列表,因此它会引发ClassCastException。我不知道为什么。

我的标题如下:

Content-Type: application/json; charset=utf-8
java.lang.ClassCastException: java.util.LinkedHashMap incompatible with com.kartik.springmvc.model.Config
    com.kartik.springmvc.service.ConfigPropertyService.upsertConfigurationProperties(ConfigPropertyService.java:56)
    com.kartik.springmvc.controller.ConfigController .upsertConfigurationProperties(ConfigController .java:86)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:88)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)
    java.lang.reflect.Method.invoke(Method.java:613)
    org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:213)
    org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:126)
    org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:96)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:617)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:578)
    org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:923)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
    org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:789)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:646)
   <context:annotation-config />
    <context:component-scan base-package="com.kartik.springmvc.controller" />
    <bean class="com.kartik.springmvc.controller.AppConfigPropertiesConverter" id="appConfigPropertiesConverter"/>

    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
         <property name="messageConverters">
            <list>
                <ref bean="appConfigPropertiesConverter" />
                <bean  class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" />
            </list>
        </property>
    </bean>
    <mvc:annotation-driven/>

下面给出了我的转换器实现。更新:未调用此类。

public class AppConfigPropertiesConverter extends AbstractHttpMessageConverter<Object> {

  public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");

  private Gson gson = new Gson();
  /**
   * Construct a new {@code GsonHttpMessageConverter}.
   */
  public AppConfigPropertiesConverter() {
    super(new MediaType("application", "json", DEFAULT_CHARSET), new MediaType(
        "application", "*+json", DEFAULT_CHARSET));
  }

  /** Supports only {@link Config} instances. */
  @Override
  protected boolean supports(Class<?> clazz) {
    // TODO Auto-generated method stub
    return true;
  }

  /**
   * Converts to a list of {@Config}
   */
  @Override
  protected Object readInternal(
      Class<?> clazz, HttpInputMessage inputMessage)
          throws IOException, HttpMessageNotReadableException {
    TypeToken<?> token = TypeToken.get(clazz);
    System.out.println("#################################################################3");
    Reader jsonReader =
        new InputStreamReader(inputMessage.getBody(), DEFAULT_CHARSET.displayName());
    System.out.println("####################################################################");
    try {
      return this.gson.fromJson(jsonReader, token.getType());
    } catch (JsonParseException ex) {
      throw new HttpMessageNotReadableException("Could not read JSON: " + ex.getMessage(), ex);
    }
  }

  /**
   * Write the json reprsentation to {@link OutputStream}.
   * 
   * @param config object to be serialized
   * @param output http output message
   */
  @Override
  protected void writeInternal(
      Object config, HttpOutputMessage outputMessage)
          throws IOException, HttpMessageNotWritableException {
    outputMessage.getBody().write(
        this.gson.toJson(config).getBytes(DEFAULT_CHARSET.displayName()));
  }

}

更新:增加了服务层

   public class ConfigPropertyService implements IConfigPropertyService {

  private final Log LOG = LogFactory.getLog(ConfigPropertyService.class);

  private final IConfigPropertyDao<Config> configPropertyDao;

  /**
   * Returns the instance of Dao.
   */
  @Override
  public IConfigPropertyDao<Config> getConfigPropertyDao() {
    return this.configPropertyDao;
  }

  /**
   * Initializes the data access tier.
   */

      public ConfigPropertyService(IConfigPropertyDao<Config> configPropertyDao) {
        this.configPropertyDao = Objects.requireNonNull(configPropertyDao);
      }

  /**
   * {@inheritDoc}
   * @throws ConfigServiceException if the resources can't be cleaned up successfully
   */
  @Override
  public void upsertConfigurationProperties(
      ImmutableList<Config> configModels) {

    for (Config config: configModels) {
         // This for loop throws an exception.
    }

    // Step # 2: Updating the properties. 
    this.configPropertyDao.upsertProperties(configModels);
  }


  /**
   * {@inheritDoc}
   */
  @Override
  public ImmutableList<ConfigModel> readConfigProperties() {
    return this.configPropertyDao.readProperties();

  }

}

我的请求体给出如下。它是一个带有内容类型的字符串体:application/json;charset=utf-8

[{"propertyName":"anchorIndexingFilter.deduplicate","propertyValue":"false","propertyDescription":"With this enabled the indexer will case-insensitive deduplicate hanchors\n  before indexing. This prevents possible hundreds or thousands of identical anchors for\n  a given page to be indexed but will affect the search scoring (i.e. tf=1.0f).\n  ","editable":true}]   

共有1个答案

秋光熙
2023-03-14

问题是方法签名将LinkedHashMap作为参数传递,但在方法中接收的是配置对象列表,这会导致类转换异常

public void updateConfig(@RequestBody List<Config> configList) 

将上面的内容改为类似这样的内容不完全是

public void updateConfig(@RequestBody LinkedHashMap<K,V> configList)
 类似资料:
  • 我正在尝试在更改选项后将我的Thymeleaf超文本标记语言中已经提供的List传回控制器。我尝试过隐藏输入,但不幸的是,它还不起作用。 我的表单如下所示(控制器已经提供了“电影”列表) 我的控制器看起来像这样: 期待有人能帮助我!

  • 我正在尝试将一个对象(或只是ID)传递给我的控制器,我从下拉列表中选择它。有2个类:产品和类别(产品包含一个外键,这是类别的ID)这是我如何将其加载到: 如您所见,我正在将对象类别传递到我的. jsp中。在那里我显示了用户可以选择的所有类别。 该值应该传递给我的控制器,但我不知道如何传递它。

  • 问题内容: 我正在将一个对象传递给我的控制器,如下所示: 我的控制器将其视为它正在寻找的对象: 我的问题是我只想再传递一个字符串。我知道我可以制作特定于视图的模型,但我想知道是否可以执行以下操作: 我没有运气就尝试了以下方法: 但是复杂对象只是作为null来的。有没有办法我也可以传递对象和字符串? 问题答案: 尝试将字符串项添加到已有的JSON中。不要对其进行字符串化,否则它将发送一个大字符串,您

  • 问题内容: 我有以下任意JSON对象(字段名称可能会更改)。 -- 我知道我可以像定义具有相同字段名的JSON对象那样定义类,但是我希望控制器接受具有不同字段名的任意JSON对象。 问题答案: 如果您想将自定义JSON对象传递给MVC操作,则可以使用此解决方案,它的工作原理很吸引人。 该解决方案的真正好处是,您不需要为每个参数组合定义一个新类,并且除此之外,您可以轻松地将对象转换为其原始类型。 更

  • 如果对象为NULL,则无法传递对象项目。如何将对象从HTML传递给spring控制器?

  • 问题内容: 我正在使用.Net 4,MVC 3和jQuery v1.5做一些工作 我有一个JSON对象,它可以根据调用它的页面而改变。我想将对象传递给控制器​​。 我了解如果我创建一个自定义模型,例如 并在我的控制器中使用它,例如 并使用jQuery的.ajax方法传递对象,如下所示: 这工作正常,我的JSON对象已映射到我的C#对象。我想做的是通过一个可能更改的JSON对象。当它更改时,我不需要