简体   繁体   English

java.lang.ClassCastException:com.google.gson.internal.LinkedTreeMap无法转换为java.util.LinkedHashMap

[英]java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to java.util.LinkedHashMap

I apologize for opening another question about this general issue, but none of the questions I've found on SO seem to relate closely to my issue. 对于这个一般性问题,我提出了另一个问题,我深表歉意,但是我在SO上发现的所有问题似乎都与我的问题没有密切关系。

I've got an existing, working dataflow pipeline that accepts objects of KV<Long, Iterable<TableRow>> and outputs TableRow objects. 我有一个现有的工作数据流管道,该管道接受KV<Long, Iterable<TableRow>>对象并输出TableRow对象。 This code is in our production environment, running without issue. 该代码在我们的生产环境中,可以正常运行。 I am now trying to implement a unit test with direct runner to test this pipeline, however, but the unit test fails when it hits the line 我现在正在尝试使用直接运行程序来实现单元测试以测试该管道,但是当单元测试到达该行时,单元测试将失败

LinkedHashMap<String, Object> evt = (LinkedHashMap<String, Object>) row.get(Schema.EVT);

in the pipeline, throwing the error message: 在管道中,抛出错误消息:

java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to java.util.LinkedHashMap java.lang.ClassCastException:com.google.gson.internal.LinkedTreeMap无法转换为java.util.LinkedHashMap

A simplified version of the existing dataflow code looks like this: 现有数据流代码的简化版本如下所示:

public static class Process extends DoFn<KV<Long, Iterable<TableRow>>, TableRow> {

    /* private variables */

    /* constructor */

    /* private functions */

    @ProcessElement
    public void processElement(ProcessContext c) throws InterruptedException, ParseException {       

      EventProcessor eventProc = new EventProcessor();
      Processor.WorkItem workItem = new Processor.WorkItem();
      Iterator<TableRow> it = c.element().getValue().iterator();

      // process all TableRows having the same id
      while (it.hasNext()) {
        TableRow item = it.next();

        if (item.containsKey(Schema.EVT))
          eventProc.process(item, workItem);
        else
          /* process by different Proc class */
      }

      /* do additional logic */

      /* c.output() is somewhere far below */

    }
}

public class EventProcessor extends Processor {

    // Extract data from an event into the WorkItem
    @SuppressWarnings("unchecked")
    @Override
    public void process(TableRow row, WorkItem item) {    

        try {
          LinkedHashMap<String, Object> evt = (LinkedHashMap<String, Object>) row.get(Schema.EVT);
          LinkedHashMap<String, Object> profile = (LinkedHashMap<String, Object>) row.get(Schema.PROFILE);

          /* if no exception, process further business logic */

          /* business logic */

        } catch (ParseException e) {
            System.err.println("Bad row");
        }
    }
}      

The relevant portion of the unit test, which prepares the main input to the Process() DoFn , looks like this: 单元测试的相关部分准备了Process() DoFn的主要输入,如下所示:

Map<Long, List<TableRow>> groups = new HashMap<Long, List<TableRow>>();
List<KV<Long, Iterable<TableRow>>> collections = new ArrayList<KV<Long,Iterable<TableRow>>>();    
Gson gson = new Gson();    

// populate the map with events grouped by id
for(int i = 0; i < EVENTS.length; i++) {
  TableRow row = gson.fromJson(EVENTS[i], TableRow.class);
  Long id = EVENT_IDS[i];

  if(groups.containsKey(id))
    groups.get(id).add(row);
  else
    groups.put(id, new ArrayList<TableRow>(Arrays.asList(row)));        
}

// prepare main input for pipeline
for(Long key : groups.keySet())
  collections.add(KV.of(key, groups.get(key)));

The line which is causing the issue is gson.fromJson(EVENTS[i], TableRow.class); 导致该问题的行是gson.fromJson(EVENTS[i], TableRow.class); , which appears to be encoding the internal representation of the TableRow as the wrong type of LinkedTreeMap. ,似乎正在将TableRow的内部表示形式编码为LinkedTreeMap的错误类型。

The encoded type of the TableRow appears to be com.google.gson.internal.LinkedTreeMap instead of the expected java.util.LinkedHashMap . TableRow的编码类型似乎是com.google.gson.internal.LinkedTreeMap而不是预期的java.util.LinkedHashMap Is there a way I can cast the TableRow being created in my unit test to the correct type of java.util.LinkedHashMap , so that the unit test succeeds without making any changes to the existing dataflow code that already works in production? 有没有一种方法可以将在单元测试中创建的TableRow强制转换为java.util.LinkedHashMap的正确类型,以便单元测试成功而无需对已在生产环境中使用的现有数据流代码进行任何更改?

Reposting the solution as an answer. 重新发布解决方案作为答案。

It is not recommended to cast to concrete classes if you do not use their specific features. 如果不使用具体类,则不建议将其转换为具体类。 In this case, it is better to cast to Map instead of LinkedHashMap . 在这种情况下,最好将其强制转换为Map而不是LinkedHashMap Gson's LinkedTreeMap is a Map too, so no problem should arise. Gson的LinkedTreeMap也是一个Map ,因此不会出现任何问题。

It's because LinkedHashMap is not superior to LinkedTreeMap thus they might not have the same methods. 这是因为LinkedHashMap不优于LinkedTreeMap,因此它们可能没有相同的方法。 The Java compiler so thinks that casting it that way might result in evt having different methods than row.get(Schema.EVT) , resulting bad stuff. Java编译器因此认为,以这种方式进行转换可能会导致evt具有与row.get(Schema.EVT)不同的方法,从而导致不良row.get(Schema.EVT) However, you can cast LinkedTreeMap into AbstractMap, Map or Object as they're all superior to it. 但是,您可以将LinkedTreeMap投射到AbstractMap,Map或Object中,因为它们都优于它。 So (as many comments point out) to fix it, just use 因此(正如许多评论所指出的)要对其进行修复,只需使用

Map<String, Object> evt = row.get(Schema.EVT);

and you should be fine. 你应该没事的

I would consider (not only that particular) cast a code smell . 我会(不仅是那个)考虑一下代码的味道 Every time a cast is coded, a risk is taken that a ClassCastException happens. 每次对强制类型转换进行编码时,都会冒ClassCastException发生的风险。

As the others already said, the Map interface could be used like Map<String, Object> evt = row.get(Schema.EVT); 正如其他人已经说过的那样,可以像Map<String, Object> evt = row.get(Schema.EVT);一样使用Map接口Map<String, Object> evt = row.get(Schema.EVT); .

Alternatively, a new LinkedHashMap could be constructed by new LinkedHashMap<String, Object>(row.get(Schema.EVT)); 可替代地,一个新LinkedHashMap可以通过构建new LinkedHashMap<String, Object>(row.get(Schema.EVT)); .

The second approach has the advantage of keeping the LinkedHashMap type, which might or might not be important, that depends on your scenario. 第二种方法的优点是可以保留LinkedHashMap类型,该类型可能重要也可能不重要,具体取决于您的方案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to com.google.gson.internal.LinkedTreeMap - java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to com.google.gson.internal.LinkedTreeMap java.lang.ClassCastException:com.google.gson.internal.LinkedTreeMap无法强制转换为com.example - java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to com.example java.lang.ClassCastException:com.google.gson.internal.LinkedTreeMap 无法转换为模型 - java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to model Android:Loop for正在获取java.lang.ClassCastException:com.google.gson.internal.LinkedTreeMap无法强制转换 - Android: Loop for is getting java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast 线程“主”中的异常 java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap 无法转换 - Exception in thread “main” java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast t java.lang.ClassCastException:com.google.gson.internal.LinkedTreeMap无法转换为asd.Grade - java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to asd.Grade java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap 无法转换为模型类 android - java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to model class android java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to pojo.class - java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to pojo.class 为什么 java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap 无法转换为 com.readbook.chinesepoetry.data.model.Response? - why java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to com.readbook.chinesepoetry.data.model.Response? 传递参数的通用方法-java.lang.ClassCastException:com.google.gson.internal.LinkedTreeMap - generic method passing parramaters - java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM