【问题标题】:Restlet converts JSON to LinkedHashMap instead of List<MyObject>?Restlet 将 JSON 转换为 LinkedHashMap 而不是 List<MyObject>?
【发布时间】:2015-05-20 05:07:46
【问题描述】:

这就是我的Rest 端点的样子

  @Post("json")
  public List<LogProcessorExpression> addLogProcessorExpression(
      final List<LogProcessorExpression> expressions) throws LPRestletException {
    if (expressions == null || expressions.isEmpty()) {
      return Collections.emptyList();
    }

    final Integer currentTenantId = Utils.getCurrentTenantId(getRequest());
    return customAttributesManager.addLogProcessorExpression(currentTenantId, expressions);
  }

它调用的方法看起来像

List<LogProcessorExpression> addLogProcessorExpression(final Integer currentTenantId,
                                                       final List<LogProcessorExpression> expressions)
      throws LPRestletException {
    final Map<String, LogProcessorExpression> cache = getCacheByCustomAttributeName(expressions);
    try {
      final List<Customattributesmetadata> cams =
          getCustomAttributesMetaDataForTenant(currentTenantId);

      for (final Customattributesmetadata metadata : cams) {
        if (cache.containsKey(metadata.getAttributecolumnname())) {
          metadata.setLogprocessorexpression(
              cache.get(metadata.getAttributecolumnname()).toString());
        }
        metadata.save();
      }
    } catch (final TorqueException e) {
      final String error = "Failed to update LogExpression custom attributes";
      LOGGER.error(error, e);
      throw new LPRestletException(error, e);
    }

    return expressions;
  }

调用链中的其他方法。当我以

身份访问此端点时,我意识到了什么
 curl -v -H "Authorization:Basic Y3VyYasqrwqrjQGdtYWlsLmNvbTp0YXAzYWg=" \
     -H "Content-Type:application/json" \
     -d '[{"source": "ad", "attributePrefix": "ad_", "attributeName": "department"}]' \
     http://172.11.041.240:8080/api/rest/msp/attributes

它返回

{
   "code" : 500
   "message" : "The server encountered an unexpected condition which prevented it from fulfilling the request",
}

当我查看日志时,我看到的行是

        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1515)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to com.shn.api.dto.LogProcessorExpression
        at com.shn.api.restlet.logprocessor.CustomAttributesManager.getCacheByCustomAttributeName(CustomAttributesManager.java:55)
        at com.shn.api.restlet.logprocessor.CustomAttributesManager.addLogProcessorExpression(CustomAttributesManager.java:24)
        at com.shn.api.restlet.logprocessor.CustomAttributeMetadataRestlet.addLogProcessorExpression(CustomAttributeMetadataRestlet.java:44)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at org.restlet.resource.ServerResource.doHandle(ServerResource.java:521)
        ... 67 more

问题
- 为什么不将它们投射到List&lt;LogProcessorExpression&gt;
- 我需要做什么来修复它?

更新

第 24 行看起来像

final Map<String, LogProcessorExpression> cache = getCacheByCustomAttributeName(expressions);  

第 44 行看起来像

return customAttributesManager.addLogProcessorExpression(currentTenantId, expressions);  

getCacheByCustomAttributeName(expressions) 看起来像

  Map<String, LogProcessorExpression> getCacheByCustomAttributeName(
      final List<LogProcessorExpression> expressions) {
    if (expressions == null || expressions.isEmpty()) {
      return Collections.emptyMap();
    }

    final Map<String, LogProcessorExpression> attributeByExpression = new HashMap<>();
    for (final LogProcessorExpression expression : expressions) {
      attributeByExpression.put(expression.getAttributeName(), expression);
    }
    return attributeByExpression;
  }

【问题讨论】:

  • 这个 addLogProcessorExpression 方法的返回类型是什么
  • 刚刚更新,谢谢
  • 添加行号 24 和 44
  • 完成,您需要的一切
  • 我猜我的DTO 需要实现Serializable,对吧?

标签: java json restlet restlet-2.0


【解决方案1】:

我认为restlet 可能不够复杂,无法从处理程序方法的参数列表中提取参数化类型List&lt;LogProcessorExpression&gt;

@Post("json")
public List<LogProcessorExpression> addLogProcessorExpression(
  final List<LogProcessorExpression> expressions)

它只需要List 并且可能在反序列化时使用它(与杰克逊一起)。当没有提供反序列化目标类型时,Jackson 使用 LinkedHashMap 作为反序列化目标类型。

没有更好地实现这一点的restlet(也许在较新的版本中?),一个潜在的解决方案是定义一个自定义类型

class LogProcessorExpressionList extends ArrayList<LogProcessorExpression> {}

并使用该类型作为参数类型

@Post("json")
public List<LogProcessorExpression> addLogProcessorExpression(
  final LogProcessorExpressionList expressions)

然后,Jackson 可以提取LogProcessorExpressionList 类型的参数化超类型,即ArrayList&lt;LogProcessorExpression&gt;,从中可以提取LogProcessorExpression 作为目标元素类型。

【讨论】:

  • 有趣,现在我看到{"code":422,"message":"The server understands the content type of the request entity and the syntax of the request entity is correct but was unable to process the contained instructions"}
  • 我需要 Getters/Setters 和 LogProcessorExpression 的空构造函数,这解决了您的解决方案的问题
【解决方案2】:

也许您可以为此使用自定义 Jackson 反序列化器?有关此功能,请参阅此链接:http://www.baeldung.com/jackson-deserialization

此答案为您提供了一些配置 Jackson ObjectMapper: How to register Jackson Jdk8 module in Restlet 的提示。这允许注册自定义反序列化器并参与反序列化处理以在您的列表中创建正确的对象。

希望对你有帮助 蒂埃里

【讨论】:

    【解决方案3】:

    这对我有用..

    class LogProcessorExpressionList extends ArrayList<LogProcessorExpression> {}
    

    【讨论】:

      猜你喜欢
      • 2011-11-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-29
      • 2018-11-28
      • 1970-01-01
      相关资源
      最近更新 更多