gson 反序列化包含java.lang.CharSequence成员变量的类

xytpbqjk  于 2022-11-06  发布在  Java
关注(0)|答案(3)|浏览(149)

我有一个简单的类,包含java.lang.CharSequence类型的name变量

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的无参数构造函数。使用此类型的Gson注册InstanceCreator可能会解决此问题。
如何解决此问题?我无法将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);

现在它又给了我一个错误:
路径$.name的第1行第10列应为开始_OBJECT,但为STRING
我错过了什么?
我不认为这是一个重复。所有其他问题都是关于将一个类或接口作为一个整体进行反序列化。我遇到了一个问题,这个类将接口引用作为成员变量。我无法从类似的答案中解决这个问题。

thtygnil

thtygnil1#

CharSequence是一个接口。
当Gson试图将一个json字符串反序列化为一个对象时,它会“内省”该对象(通过使用反射),并试图解析字段的类型,然后它会尝试创建当时的字段。
开箱即用,Gson可以处理许多“广泛”的类型,如String、Integer、Boolean等,然而,当它的一些东西GSon是不知道的(如在这种情况下的CharSequence),GSon停止与错误。
现在很清楚,你应该“教”Gson理解这个自定义类型。为此,Gson中有类型适配器。
Here你可以找到一个关于使用适配器的简短教程。我不会在这里重新编写一个例子,但是一般来说你应该创建一个适配器,在Gson对象上注册它并调用你的代码。当Gson到达CharSequence字段时,它会找到这个自定义适配器并调用它

km0tfn4u

km0tfn4u2#

正如在其他答案中提到的,Gson没有CharSequence的内置适配器(请参见related pull request),因此无法对其进行反序列化。
但是,您可以通过编写自定义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()协定。
您必须使用GsonBuilder注册该适配器,然后使用该适配器创建Gson示例:

Gson gson = new GsonBuilder()
    .registerTypeAdapter(CharSequence.class, new CharSequenceTypeAdapter())
    .create();

或者,如果您实际上始终使用String作为CharSequence值,那么您也可以将字段类型更改为String,以防这对代码的API没有任何负面影响。

xxe27gdn

xxe27gdn3#

您不需要in.beginObject();行,没有这行代码就可以正常工作。

相关问题