Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用GSON将Java接口转换为JSON字符串,而不在JSON对象中封装序列化? 背景_Java_Json_Serialization_Gson - Fatal编程技术网

使用GSON将Java接口转换为JSON字符串,而不在JSON对象中封装序列化? 背景

使用GSON将Java接口转换为JSON字符串,而不在JSON对象中封装序列化? 背景,java,json,serialization,gson,Java,Json,Serialization,Gson,我想将接口序列化为JSON对象。例如,假设我有以下接口: public interface Person { String getName(); int getAge(); } Person person = new PersonImpl("Bob", 42); GsonBuilder builder = new GsonBuilder(); builder.registerTypeAdapter(Person.class, new PersonSerializer()); G

我想将接口序列化为JSON对象。例如,假设我有以下接口:

public interface Person {
    String getName();
    int getAge();
}
Person person = new PersonImpl("Bob", 42);
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(Person.class, new PersonSerializer());
Gson gson = builder.create();
String personAsJsonString = gson.toJson(person); // Breakpoint BP2
它由类
PersonImpl
实现:

public class PersonImpl implements Person {
    private String name;
    private int age;

    public PersonImpl(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public int getAge() {
        return age;
    }
}
PersonSerializer.java
用于使用GSON序列化接口:

public class PersonSerializer implements JsonSerializer<Person> {

    @Override
    public JsonElement serialize(Person src, Type typeOfSrc, JsonSerializationContext context) {
        JsonObject person = new JsonObject();
        person.addProperty("name", src.getName());
        person.addProperty("age", src.getAge());
        return person; // Breakpoint BP1
    }
}
问题 问题是
Person
类正在序列化,如下所示:

// Not what I want
{
    "person": {
        "name": "Bob",
        "age": 42
    }
}
但是,我只需要
person
中的数据:

// What I want
{
    "name": "Bob",
    "age": 42
}
故障排除与调试 在断点BP1处(通过注释注释),person的字符串值正是我想要的。但是,通过断点BP2,在GSON完成接口的序列化(即
personAsJsonString
)之后,这是不希望出现的结果

如何让GSON序列化自定义接口而不将结果封装在JSON对象中

编辑(找到根本原因) 我完全没有提到我使用的是Decorator模式,这恰好是问题的根本原因

public abstract class PersonDecorator implements Person {
    protected Person person;

    public PersonDecorator(Person person) {
        this.person = person;
    }

    @Override
    public String getName() {
        return person.getName();
    }

    @Override
    public int getAge() {
        return person.getAge();
    }
}
下面是一个装饰器示例:

public class MrPersonDecorator extends PersonDecorator {
    public MrPersonDecorator(Person person) {
        super(person);
    }

    @Override
    public String getName() {
        return "Mr. " + person.getName();
    }
}
因此,通过decorator创建
Person
实例时出现了问题:

Person person = new MrPersonDecorator(new PersonImpl("Bob", 42));

在本例中,我没有得到对接口本身的引用,而是得到了decorator,它还包含了接口的一个实例以及接口的实现。

Gson没有提供这种机制(请注意,它不是主要约束,例如,Jackson通过
@JsonUnwrapped
注释或
序列化功能提供它。在映射器上展开根值)

您可以为适配器提供自定义序列化程序,如下所示:

public class PersonDecoratorSerializer implements JsonSerializer<PersonDecorator> {

    @Override
    public JsonElement serialize(PersonDecorator src, Type typeOfSrc, JsonSerializationContext context) {
        return context.serialize(src.getOriginalPerson()); 
    }
}

我无法复制此问题。您使用的是哪个版本的gson?@qwwdfsad 2.3.1。您使用的是哪个版本?您的问题中的大小写被序列化,没有rootname(应该是这样的)。请指定问题或检查代码please@qwwdfsad您尝试了哪个版本的GSON?@qwwdfsad我找到了根本原因并更新了问题。谢谢您的帮助!
public static String toJson(Person person, Gson gson) {
    JsonObject object = gson.toJsonTree(person).getAsJsonObject();
    // Checks whether Person was PersonDecorator or not
    if (object.has("person")) {
      return object.get("person").toString();
    } else {
      return object.toString();
    }
}