在jackson中,我们可以使用注释
要实现多态序列化,请执行以下操作。
我们可以选择
这两种解决方案都有一个问题:编写代码时必须知道所有子类。
在GraphQL中
判别器字段是固定的:"__typename"
所有的需求都是固定的,这意味着没有必要一个一个地配置子类型,可以创建一个jackson模块来自动处理它们。
// 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 ...
}使用代码如下所示
BookStore store = ...;
ObjectMapper mapper = new ObjectMapper();
mapper.addModule(new GraphQLModule());
System.out.println(mapper.writeValueAsString(store));在这里,我们需要创建"GraphQLModule",它可以处理所有子类型,实现空接口"GraphQLObject",并告诉杰克逊如何使用每个子类型的简单类名作为判别器字段"__typename“的值。
结果应该是:
{
name: "store",
books: [
{ __typename: "ElectronicBook", name: "book-1" },
{ __typename: "PaperBook", name: "book-2" }
]
}是否有可能实现"GraphQLModule"?
注:
和jackson的默认多态行为一样,只有当对象运行时类型与编译时已知的列表的泛型类型参数不同时,才需要添加判别器字段。
发布于 2022-01-11 18:25:42
可以实现扩展GraphQLModule类的“SimpleModule”模块:
public class GraphQLModule extends SimpleModule {
public GraphQLModule() {
this.addSerializer(new GraphQLSerializer());
}
}我在模块中添加了一个新的序列化程序,它扩展了StdSerializer类:
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中,并在下面的示例中使用它:
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));发布于 2022-01-11 21:47:10
我找到了原因。
我试图定义客户序列化程序,但我发现"serializeWithType“从未被调用过。
在我的项目中,数据类型是接口。我使用ASM来生成它的字节码。我只生成了最简单的字节码,忽略了泛型的签名。
所以,在整数中,它是列表
但是,在我的字节码实现中,它是列表
https://stackoverflow.com/questions/70665117
复制相似问题