Java Gson错误:Json具有映射时JsonSyntaxException
我正在读取一个Json字符串,并使用scala代码将其转换为一个对象:Java Gson错误:Json具有映射时JsonSyntaxException,java,json,scala,Java,Json,Scala,我正在读取一个Json字符串,并使用scala代码将其转换为一个对象: val myInstance = (new Gson()).fromJson(t, classOf[myClass]) 在我在“myClass”类中添加哈希映射之前,一切都正常。然后对于以下Json输入(friends是一个hashMap) 然后我在“firstname”属性中得到了如下错误。有人知道吗?多谢各位 15/07/29 08:43:05 ERROR Executor: Exception in task 0.0
val myInstance = (new Gson()).fromJson(t, classOf[myClass])
在我在“myClass”类中添加哈希映射之前,一切都正常。然后对于以下Json输入(friends是一个hashMap)
然后我在“firstname”属性中得到了如下错误。有人知道吗?多谢各位
15/07/29 08:43:05 ERROR Executor: Exception in task 0.0 in stage 0.0 (TID 0)
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 51
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:176)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:40)
at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.read(MapTypeAdapterFactory.java:186)
at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.read(MapTypeAdapterFactory.java:145)
这是我的课堂:
public final class myClass extends implements Serializable {
private static final long serialVersionUID = 11271827L;
private String pId;
private String name;
private List<MyPet> pets = new ArrayList<MyPet>();
private Map<MyName, Double> friends = new HashMap<MyName, Double>();
:
//some getter/setter here
}
在json中,映射的键应该是字符串。在您的情况下,您使用
MyName
作为键。因此json解析器使用MyName#toString()
转换为字符串
我的建议是正确的MyName#toString()
实现,并在MyName类中提供一个静态方法MyName valueOf(String)
例如:
class MyName{
private String firstName;
private String lastName;
// getters and setters
@Override
public String toString(){
return firstName+" "+lastName;
}
public static MyName valueOf(String str){
int space = str.lastIndexOf(' ');
if(space==-1)
throw new IllegalArgumentException();
MyName myName = new MyName();
myName.setFirstName(str.subString(0, space));
myName.setLastName(str.subString(space+1));
return myName;
}
}
这里的valueOf
和toString
实现应该是兼容的
上面的代码假设json中的
lastName
中没有空格,map的键应该是string。在您的情况下,您使用MyName
作为键。因此json解析器使用MyName#toString()
转换为字符串
我的建议是正确的MyName#toString()
实现,并在MyName类中提供一个静态方法MyName valueOf(String)
例如:
class MyName{
private String firstName;
private String lastName;
// getters and setters
@Override
public String toString(){
return firstName+" "+lastName;
}
public static MyName valueOf(String str){
int space = str.lastIndexOf(' ');
if(space==-1)
throw new IllegalArgumentException();
MyName myName = new MyName();
myName.setFirstName(str.subString(0, space));
myName.setLastName(str.subString(space+1));
return myName;
}
}
这里的valueOf
和toString
实现应该是兼容的
上面的代码假定
lastName
中没有空格,您所做的是一个坏主意。不要在JSON名称中提供以字符串表示的复杂对象结构
尽管如此,这里还是有一个解决方案。提供并注册自定义JsonDeserializer
Gson gson = new GsonBuilder().registerTypeAdapter(MyName.class, new KeyDeserializer()).create();
...
class KeyDeserializer implements JsonDeserializer<MyName> {
private Gson gson = new Gson();
@Override
public MyName deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
return gson.fromJson(json.getAsString(), MyName.class);
}
}
然后,我们使用一个单独的
Gson
实例将其反序列化为具有默认行为的MyName
实例。我们需要第二个Gson
实例,因为原始实例已经注册了用于自定义反序列化的KeyDeserializer
。您所做的是一个坏主意。不要在JSON名称中提供以字符串表示的复杂对象结构
尽管如此,这里还是有一个解决方案。提供并注册自定义JsonDeserializer
Gson gson = new GsonBuilder().registerTypeAdapter(MyName.class, new KeyDeserializer()).create();
...
class KeyDeserializer implements JsonDeserializer<MyName> {
private Gson gson = new Gson();
@Override
public MyName deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
return gson.fromJson(json.getAsString(), MyName.class);
}
}
然后,我们使用一个单独的
Gson
实例将其反序列化为具有默认行为的MyName
实例。我们需要第二个Gson
实例,因为原始实例已经注册了用于自定义反序列化的KeyDeserializer
。此“{\“firstname\”:“John\”,““lastname\”:“Smith\”}”
是一个JSON字符串。你想把它反序列化成什么?向我们展示什么是myClass
。注意name
字段和firstname
字段之间的差异。请参见firstname
周围引号前的反斜杠?它是json输入中的一个字符串。我猜您没有指定映射的类型,即,HashMap
。我在上面添加了myClass定义。谢谢抱歉,在myClass中:{\'firstname\':\'John\',\'lastname\':\'Smith\'}是我项目中MyName类的成员,这似乎是导致问题的原因。然而,另一个MyPet是一个列表,它运行良好。为什么列表可以工作而Map不能?您可能必须使用GsonBuilder
构建一个自定义反序列化程序:这个“{\“firstname\”:“John\”,““lastname\”:“Smith\”}”
是一个JSON字符串。你想把它反序列化成什么?向我们展示什么是myClass
。注意name
字段和firstname
字段之间的差异。请参见firstname
周围引号前的反斜杠?它是json输入中的一个字符串。我猜您没有指定映射的类型,即,HashMap
。我在上面添加了myClass定义。谢谢抱歉,在myClass中:{\'firstname\':\'John\',\'lastname\':\'Smith\'}是我项目中MyName类的成员,这似乎是导致问题的原因。然而,另一个MyPet是一个列表,它运行良好。为什么列表可以工作而Map不能?您可能需要使用GsonBuilder
构建自定义反序列化程序:非常感谢!我在上面添加了MyName类。它已经覆盖了toString方法,这还不够吗?请您详细说明一下“在MyName类中提供一个静态方法MyName valueOf(String)”?非常感谢。valueOf
方法将做什么?为什么这样认为?java的惯例是使用静态方法valueOf(String)
从字符串表示构造。例如,请参见Integer.valueOf(String)
,Float.valueOf(String)
等。json解析器使用此约定将字符串表示转换为特定对象。事情不会因为约定而神奇地发生。Gson将如何使用的值?谢谢大家!我想知道,如果我的toString()函数已经输出了一个Json字符串,为什么我不能执行以下操作:public static MyName valueOf(string str){return(new Gson()).fromJson(str,MyName.class);}非常感谢!我在上面添加了MyName类。它已经覆盖了toString方法,这还不够吗?请您详细说明一下“在MyName类中提供一个静态方法MyName valueOf(String)”?非常感谢。valueOf
方法将做什么?为什么这样认为?java的惯例是使用静态方法valueOf(String)
从字符串表示构造。例如,请参见Integer.valueOf(String)
,Float.valueOf(String)
等。json解析器使用此约定将字符串表示转换为特定对象。事情不会因为约定而神奇地发生。Gson将如何使用
的值?谢谢大家!我想知道,如果我的toString()函数已经输出了一个Json字符串,为什么我不能执行以下操作:public static MyName valueOf(string str){return(new Gson()).fromJson(str,MyName.class);}
{"firstname":"John","lastname":"Smith"}