首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用out注解和混音实现多态序列化

如何使用out注解和混音实现多态序列化
EN

Stack Overflow用户
提问于 2022-01-11 10:21:33
回答 2查看 201关注 0票数 1

在jackson中,我们可以使用注释

  1. @JsonTypeInfo
  2. @JsonSubTypes
  3. @JsonSubTypes.Type

要实现多态序列化,请执行以下操作。

我们可以选择

  1. 直接在数据模型上使用这些注释,这是最简单的方法。
  2. 使用这些注释。这里有一个关于它的链接,Polymorphic deserialization in Jackson without annotations.

这两种解决方案都有一个问题:编写代码时必须知道所有子类。

在GraphQL中

判别器字段是固定的:"__typename"

  • The子类型名称也是固定的: java类的简单名称

所有的需求都是固定的,这意味着没有必要一个一个地配置子类型,可以创建一个jackson模块来自动处理它们。

代码语言:javascript
复制
// An empty interface
// Developers need not to configure polymorphic metadata for any class of its subtypes 
public interface GraphQLObject {}

public class BookStore implements GraphQLObject {
    public List<Book> getBooks() {...}
    ...other gettes/setters...
}
public abstract class Book implements GraphQLObject {
    ... some properties ...
}
public class ElectronicBook extends Book {
    ... some properties ...
}
public class PaperBook extends Book {
    ... some properties ...
}

使用代码如下所示

代码语言:javascript
复制
BookStore store = ...;
ObjectMapper mapper = new ObjectMapper();
mapper.addModule(new GraphQLModule());
System.out.println(mapper.writeValueAsString(store));

在这里,我们需要创建"GraphQLModule",它可以处理所有子类型,实现空接口"GraphQLObject",并告诉杰克逊如何使用每个子类型的简单类名作为判别器字段"__typename“的值。

结果应该是:

代码语言:javascript
复制
{
   name: "store",
   books: [
     { __typename: "ElectronicBook", name: "book-1" },
     { __typename: "PaperBook", name: "book-2" }
   ]
}

是否有可能实现"GraphQLModule"?

注:

和jackson的默认多态行为一样,只有当对象运行时类型与编译时已知的列表的泛型类型参数不同时,才需要添加判别器字段。

EN

回答 2

Stack Overflow用户

发布于 2022-01-11 18:25:42

可以实现扩展GraphQLModule类的“SimpleModule”模块:

代码语言:javascript
复制
public class GraphQLModule extends SimpleModule {

    public GraphQLModule() {
        this.addSerializer(new GraphQLSerializer());
    }
}

我在模块中添加了一个新的序列化程序,它扩展了StdSerializer类:

代码语言:javascript
复制
public class GraphQLSerializer extends StdSerializer<GraphQLObject> {

    public GraphQLSerializer() {
        super(GraphQLObject.class);
    }

    @Override
    public void serialize(GraphQLObject obj, JsonGenerator jg, SerializerProvider sp) throws IOException {
        jg.writeStartObject();
        jg.writeStringField("__typename", obj.getClass().getSimpleName());
        jg.writeEndObject();
    }
    
}

GraphQLSerializer序列化器只需将实现GraphQLObject接口的对象序列化(包括json中的对象),只需将对象的类名字符串作为__typename

因此,您可以将这个模块添加到您的objectMapper中,并在下面的示例中使用它:

代码语言:javascript
复制
public interface GraphQLObject {}
public abstract class Book implements GraphQLObject {}
public class ElectronicBook extends Book {}
public class PaperBook extends Book {}

ObjectMapper objectMapper = new ObjectMapper();
mapper.registerModule(new GraphQLModule());
List<Book> books = List.of(new ElectronicBook(), new PaperBook());
//it will print [{"__typename":"ElectronicBook"},{"__typename":"PaperBook"}]
System.out.println(mapper.writeValueAsString(books));
票数 0
EN

Stack Overflow用户

发布于 2022-01-11 21:47:10

我找到了原因。

我试图定义客户序列化程序,但我发现"serializeWithType“从未被调用过。

在我的项目中,数据类型是接口。我使用ASM来生成它的字节码。我只生成了最简单的字节码,忽略了泛型的签名。

所以,在整数中,它是列表

但是,在我的字节码实现中,它是列表

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70665117

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档