我有一个简单的类name
其中包含java.lang.CharSequence
类型的变量
class Person {
public java.lang.CharSequence name;
}
当我尝试使用 GSON 库反序列化 JSON 字符串时
Person p;
Gson gson = new Gson();
String json = "{"name":"dinesh"}";
p = gson.fromJson(json, Person.class);
System.out.println(p);
它给了我以下错误:
java.lang.RuntimeException:无法为接口 java.lang.CharSequence 调用 no-args 构造函数。向 Gson 注册此类型的实例创建者可能会解决此问题。
我该如何解决这个问题?我无法将Person.name
类型更改为String
。
正如评论中所建议的,
我为CharSequence
创建了一个自定义适配器
class CharSequenceAdapter extends TypeAdapter<CharSequence> {
@Override
public void write(JsonWriter out, CharSequence value) throws IOException {
}
@Override
public CharSequence read(JsonReader in) throws IOException {
String s = new String();
in.beginObject();
while(in.hasNext()) {
s = in.nextString();
}
return s;
}
}
我的 GSON 构建器看起来像这样:
Person p;
GsonBuilder builder = new GsonBuilder().registerTypeAdapter(java.lang.CharSequence.class, new CharSequenceAdapter());
Gson gson = builder.create();
String json = "{"name":"dinesh"}";
p = gson.fromJson(json, Person.class);
System.out.println(p);
现在它给了我另一个错误:
预期BEGIN_OBJECT,但第 1 行第 10 列路径 $.name 处是字符串
我错过了什么?
我不认为这是重复的。所有其他问题都讨论将一个类或接口作为一个整体进行反序列化。我遇到一个将接口引用作为成员变量的类的问题。我无法从类似的答案中解决问题。
CharSequence是一个接口。
当 Gson 尝试将 json 字符串反序列化为对象时,它会"内省"对象(通过使用反射(并尝试解析字段类型。 然后,它尝试创建当时的字段。
开箱即用的Gson可以处理许多"广泛"的类型,如字符串,整数,布尔值等,但是当GSon不知道它的东西时(如本例中的CharSequence(,GSon会停止错误。
现在很明显,您应该"教"Gson理解此自定义类型。 为此,Gson 中有类型适配器。
在这里,您可以找到有关使用适配器的简短教程。 我不会在这里重写一个示例,但一般来说,你应该创建一个适配器,在 Gson 对象上注册它并调用你的代码。当 Gson 到达 CharSequence 字段时,它将找到此自定义适配器并调用它
如其他答案所述,Gson 没有用于CharSequence
的内置适配器(请参阅相关的拉取请求(,因此无法反序列化它。
但是,您可以通过编写自定义TypeAdapter
来解决此问题,例如:
class CharSequenceTypeAdapter extends TypeAdapter<CharSequence> {
@Override
public void write(JsonWriter out, CharSequence value) throws IOException {
if (value == null) {
out.nullValue();
} else {
// Assumes that value complies with CharSequence.toString() contract
out.value(value.toString());
}
}
@Override
public CharSequence read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
// Skip the JSON null
in.skipValue();
return null;
} else {
return in.nextString();
}
}
}
这假设您的CharSequence
值被编码为 JSON 字符串值(例如"value"
(,而不是作为 JSON 对象 ({ ... }
(。对于序列化,它还假定您使用的值符合CharSequence.toString()
协定。
然后,您必须使用用于创建Gson
实例的GsonBuilder
注册适配器:
Gson gson = new GsonBuilder()
.registerTypeAdapter(CharSequence.class, new CharSequenceTypeAdapter())
.create();
或者,如果您实际上总是使用String
作为CharSequence
值,那么您也可以将字段类型更改为String
,以防这对代码的 API 没有任何负面影响。
你不需要in.beginObject();
行。如果没有该行,代码可以正常工作。