【问题标题】:ClassCastException when convert json to list of objects将 json 转换为对象列表时出现 ClassCastException
【发布时间】:2014-04-02 15:30:42
【问题描述】:

我正在使用Jackson库来处理json数据。

我创建了一个 generic 函数来将 json 字符串转换为模型类对象:

public <T> T parseJsonToObject(String jsonStr, Class<T> clazz) {
    ObjectMapper mapper = new ObjectMapper();
    try {
      return mapper.readValue(jsonStr, clazz);
    } catch (Exception e) {

    }

     return null; 
}

我有一个 Person 类:

public class Person{
   @JsonProperty("first_name")
   private String firstName;

   @JsonProperty("last_name")
   private String lastName;
   //Getter & Setters ...
}

我得到了服务器响应,这是一个人员列表:

[{"first_name":"John","last_name":"Smith"},{"first_name":"Kate","last_name":"Green"}]

我的String jsonPersonsStr 持有上面的 json 字符串。

现在我尝试使用我的函数将 json 字符串直接转换为人员列表:

List<Person> persons = parseJsonToObject(jsonPersonsStr, ArrayList.class);

但我得到了例外:

java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to com.my.models.Person

如何修改我的泛型函数以消除此异常?

【问题讨论】:

标签: java json


【解决方案1】:

您可能做的最好的事情是支持Collection 类型的一种通用方法,并可能支持非Collection 类型的其他方法。

这是通用 Collection 方法的工作版本:

import org.codehaus.jackson.map.type.TypeFactory;

//...

@SuppressWarnings({ "deprecation", "rawtypes" })
public static <E, T extends Collection> T parseJsonToObject(String jsonStr, Class<T> collectionType, Class<E> elementType) {
    ObjectMapper mapper = new ObjectMapper();
    try {
        return mapper.readValue(jsonStr, TypeFactory.collectionType(collectionType, elementType));
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null; 
}

那么你可以这样称呼:

List<Person> persons = parseJsonToObject(s, ArrayList.class, Person.class);

【讨论】:

    【解决方案2】:

    试试:

    listOfObjects = mapper.readValue(connection.getInputStream(), new TypeReference<List<Person>>(){});
    

    这里的问题是由于 Java 对泛型的实现(在本例中为 List)

    【讨论】:

    • 是的,我知道这种方式可以解决问题,但是正如我所说的,函数是一个通用函数,它不仅适用于这个人员列表的 json 字符串。我正在寻找一种方法来尽可能保持函数的通用性并且可以解决我的问题。
    • 那么你会遇到问题,因为如果你的 clazz 是 List 它将无法工作
    • 您可以尝试返回新的 TypeReference(){} 而不是 clazz,但是我不确定这是否可行...
    【解决方案3】:

    请检查您的 JSON。如果我尝试使用您的信息,一切正常吗?

    试试这个静态示例。我定义了我自己的PersonList(不需要内容)

    public class JsonDeserializer {
    
        public static void main(String[] args) throws IOException {
            String jsonString = "[{\"first_name\":\"John\",\"last_name\":\"Smith\"},{\"first_name\":\"Kate\",\"last_name\":\"Green\"}]";
            List<Person> persons = parseJsonToObject(jsonString, PersonList.class);
            System.out.println("Persons: " + persons);
            for (Person person : persons) {
                System.out.println("Person " + person.firstName + " " + person.lastName);
            }
        }
    
        public static class PersonList extends ArrayList<Person> {
        } 
    
        public static <T> T parseJsonToObject(String jsonStr, Class<T> clazz) throws IOException {
            ObjectMapper mapper = new ObjectMapper();
            return mapper.readValue(jsonStr, clazz);        
        }
    
        public static class Person {
    
            @JsonProperty("first_name")
            private String firstName;
    
            @JsonProperty("last_name")
            private String lastName;
    
            @Override
            public String toString() {
                return "Person{" + "firstName=" + firstName + ", lastName=" + lastName + '}';
            }
        }
    }
    

    更新

    我使用 maven 和这个 json 库

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.0.5</version>
        <type>jar</type>
    </dependency>
    

    更新

    也适用于 Codehaus 的 jackson (1.7.3)

    <dependency>
        <groupId>org.codehaus.jackson</groupId>
        <artifactId>jackson-mapper-lgpl</artifactId>
        <version>1.7.3</version>
    </dependency>
    

    【讨论】:

    • 好吧,我不能使用这个版本的 Jackson,因为我的 Jackson 实际上是另一个 3rd 方库的内置功能。
    • 这是一个糟糕的测试。问题不在于转换为List,问题在于将列表中的元素转换为Person
    • 此测试返回一个包含Person (List&lt;Person&gt;) 对象的列表。不明白为什么这是一个糟糕的测试。
    • 它可能返回一个List&lt;Map&gt;。尝试获取其中一个元素并将其转换为Person。这就是异常发生的地方。
    • @superEb 好的,你是对的 - 对不起。我去看看。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-22
    • 1970-01-01
    • 2016-10-06
    • 1970-01-01
    • 1970-01-01
    • 2014-05-20
    相关资源
    最近更新 更多