使用XStream进行JSON反序列化遇CannotResolveClassException求助
JSON反序列化失败问题排查与解决
问题现象
XML反序列化正常,JSON反序列化时抛出如下异常,提示无法解析name类:
Exception in thread "main" com.thoughtworks.xstream.converters.ConversionException: ---- Debugging information ---- cause-exception : com.thoughtworks.xstream.mapper.CannotResolveClassException cause-message : name class : java.util.ArrayList required-type : java.util.ArrayList converter-type : com.thoughtworks.xstream.converters.collections.CollectionConverter path : /AcademicGroup/students/name line number : -1 class[1] : AcademicGroup required-type[1] : AcademicGroup converter-type[1] : com.thoughtworks.xstream.converters.reflection.ReflectionConverter version : 1.4.20 ------------------------------- at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:81) at com.thoughtworks.xstream.core.AbstractReferenceUnmarshaller.convert(AbstractReferenceUnmarshaller.java:72) at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:68) at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshallField(AbstractReflectionConverter.java:499) at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.doUnmarshal(AbstractReflectionConverter.java:425) at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshal(AbstractReflectionConverter.java:277) at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:74) at com.thoughtworks.xstream.core.AbstractReferenceUnmarshaller.convert(AbstractReferenceUnmarshaller.java:72) at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:68) at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:52) at com.thoughtworks.xstream.core.TreeUnmarshaller.start(TreeUnmarshaller.java:136) at com.thoughtworks.xstream.core.AbstractTreeMarshallingStrategy.unmarshal(AbstractTreeMarshallingStrategy.java:32) at com.thoughtworks.xstream.XStream.unmarshal(XStream.java:1464) at com.thoughtworks.xstream.XStream.unmarshal(XStream.java:1441) at com.thoughtworks.xstream.XStream.fromXML(XStream.java:1407) at com.thoughtworks.xstream.XStream.fromXML(XStream.java:1352) at AcademicGroupJSONDeserialization.main(AcademicGroupJSONDeserialization.java:14) Caused by: com.thoughtworks.xstream.mapper.CannotResolveClassException: name at com.thoughtworks.xstream.mapper.DefaultMapper.realClass(DefaultMapper.java:81) at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:125) at com.thoughtworks.xstream.mapper.DynamicProxyMapper.realClass(DynamicProxyMapper.java:55) at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:125) at com.thoughtworks.xstream.mapper.PackageAliasingMapper.realClass(PackageAliasingMapper.java:88) at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:125) at com.thoughtworks.xstream.mapper.ClassAliasingMapper.realClass(ClassAliasingMapper.java:79) at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:125) at com.thoughtworks.xstream.mapper.ArrayMapper.realClass(ArrayMapper.java:74) at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:125) at com.thoughtworks.xstream.mapper.SecurityMapper.realClass(SecurityMapper.java:71) at com.thoughtworks.xstream.mapper.MapperWrapper.realClass(MapperWrapper.java:125) at com.thoughtworks.xstream.mapper.CachingMapper.realClass(CachingMapper.java:47) at com.thoughtworks.xstream.core.util.HierarchicalStreams.readClassType(HierarchicalStreams.java:29) at com.thoughtworks.xstream.converters.collections.AbstractCollectionConverter.readBareItem(AbstractCollectionConverter.java:131) at com.thoughtworks.xstream.converters.collections.AbstractCollectionConverter.readItem(AbstractCollectionConverter.java:117) at com.thoughtworks.xstream.converters.collections.CollectionConverter.addCurrentElementToCollection(CollectionConverter.java:99) at com.thoughtworks.xstream.converters.collections.CollectionConverter.populateCollection(CollectionConverter.java:92) at com.thoughtworks.xstream.converters.collections.CollectionConverter.populateCollection(CollectionConverter.java:86) at com.thoughtworks.xstream.converters.collections.CollectionConverter.unmarshal(CollectionConverter.java:81) at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:74) ... 16 more Process finished with exit code 1
待反序列化的JSON内容:
{"AcademicGroup": { "students": [ { "name": "John Doe", "age": 20 }, { "name": "Jane Smith", "age": 22 } ] }}
用到的代码
序列化代码
import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.io.json.JsonHierarchicalStreamDriver; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; public class AcademicGroupSerialization { public static void main(String[] args) { AcademicGroup academicGroup = new AcademicGroup(); Student student1 = new Student("John Doe", 20); Student student2 = new Student("Jane Smith", 22); academicGroup.addStudent(student1); academicGroup.addStudent(student2); // Serializing to xml XStream xStream = new XStream(); xStream.alias("AcademicGroup", AcademicGroup.class); String xml = xStream.toXML(academicGroup); try (FileWriter fw = new FileWriter("AcademicGroup.xml"); PrintWriter out = new PrintWriter(fw)) { out.println(xml); } catch (IOException e) { e.printStackTrace(); } // Serializing to JSON xStream = new XStream(new JsonHierarchicalStreamDriver()); xStream.alias("AcademicGroup", AcademicGroup.class); String json = xStream.toXML(academicGroup); try (FileWriter fw = new FileWriter("AcademicGroup.json"); PrintWriter out = new PrintWriter(fw)) { out.println(json); } catch (IOException e) { e.printStackTrace(); } } }
反序列化代码
import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver; import com.thoughtworks.xstream.security.AnyTypePermission; import java.io.File; public class AcademicGroupJSONDeserialization { public static void main(String[] args) { XStream xStream = new XStream(new JettisonMappedXmlDriver()); xStream.addPermission(AnyTypePermission.ANY); xStream.alias("AcademicGroup", AcademicGroup.class); AcademicGroup academicGroup = (AcademicGroup) xStream.fromXML(new File("AcademicGroup.json")); System.out.println(academicGroup); } }
实体类代码
import java.util.ArrayList; import java.util.List; public class AcademicGroup { private List<Student> students = new ArrayList<>(); public void addStudent(Student student) { students.add(student); } public List<Student> getStudents() { return students; } @Override public String toString() { return "Student.AcademicGroup{" + "students=" + students + '}'; } } public class Student { String name; int age; public Student(String name, int age) { this.name = name; this.age = age; } // Геттеры и сеттеры public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
问题原因
- JSON驱动不匹配:序列化用
JsonHierarchicalStreamDriver,反序列化用JettisonMappedXmlDriver,两者对JSON结构的解析逻辑不一致,导致XStream无法识别集合中的对象。 - 缺少实体类别名:未给
Student类设置XStream别名,XStream无法将JSON中的对象映射到Student类,误把name字段当作类名解析。 - 缺少无参构造函数:
Student类只有带参构造,XStream反射实例化对象时必须依赖无参构造,否则无法创建对象实例。
修复方案
1. 统一JSON驱动
序列化和反序列化使用同一种JSON驱动,两种可选方式:
方式一:统一使用JsonHierarchicalStreamDriver
修改反序列化代码,替换驱动并添加Student别名:
import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.io.json.JsonHierarchicalStreamDriver; import com.thoughtworks.xstream.security.AnyTypePermission; import java.io.File; public class AcademicGroupJSONDeserialization { public static void main(String[] args) { XStream xStream = new XStream(new JsonHierarchicalStreamDriver()); xStream.addPermission(AnyTypePermission.ANY); xStream.alias("AcademicGroup", AcademicGroup.class); xStream.alias("student", Student.class); // 给Student类添加别名 AcademicGroup academicGroup = (AcademicGroup) xStream.fromXML(new File("AcademicGroup.json")); System.out.println(academicGroup); } }
方式二:统一使用JettisonMappedXmlDriver
修改序列化代码中的JSON部分,使用JettisonMappedXmlDriver并添加Student别名:
// Serializing to JSON xStream = new XStream(new JettisonMappedXmlDriver()); xStream.alias("AcademicGroup", AcademicGroup.class); xStream.alias("student", Student.class); String json = xStream.toXML(academicGroup);
同时反序列化代码也要添加xStream.alias("student", Student.class);。
2. 给Student类添加无参构造函数
修改Student类,补充无参构造:
public class Student { String name; int age; // 添加无参构造函数 public Student() {} public Student(String name, int age) { this.name = name; this.age = age; } // 原有getter、setter和toString方法保持不变 }
3. 重新生成JSON文件
修改序列化代码后,重新运行生成新的JSON文件,再执行反序列化即可成功。
内容的提问来源于stack exchange,提问作者Давид Чобанян
相关产品推荐
相关产品推荐

