- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
能够扩展现有类型是非常棒的,因为它允许代码模块化和权限分离。我找到了关于如何扩展查询中的对象输出的好例子(见下文),但没有好的方法来扩展给定对象的输入。
为了举例,假设我们有一个类User
。
class User {
String firstName;
String lastName;
}
如果我们声明一个 bean,我们可以进行如下查询:
/**
* This is valid and can be invoked using
* query {
* user(id=1) {
* firstName
* lastName
* }
* }
*/
@GraphQLQuery(name = "user")
public User getUser(@GraphQLArgument(name = "id") long id) {
}
然后在另一个bean bean中我们可以扩展User
/**
* <<this currently works>>
* So now this query becomes valid
* query {
* user(id=1) {
* firstName
* lastName
* address { <-- this is not a top level, but extends User
* streetNam
* }
* }
* }
*/
@GraphQLQuery(name = "address")
public Address getUserAddress(@GraphQLContext User) {
}
与突变类似,我们可以定义:
/**
* <<this currently works>>
* This can be invoked using:
* mutation {
* addUser(user :{
* firstName: "John"
* lastName: "Smith"
* })
* fistName
* }
*/
@GraphQLMutation(name = "addUser")
public User addUser(@GraphQLArgument(name = "user") User user) {
}
现在我尝试添加地址
,就像我们为查询添加它一样,但添加是User
的输入参数。以下仍然在某些 bean 中声明。
/**
* << this is what I am trying to achieve>>
* I want to be able to invoke the following query and not having to declare 'Address' inside of 'User' class.
* mutation {
* addUser(user :{
* firstName: "John"
* lastName: "Smith"
* address: { <-- being able to pass address as argument now, and be part of user.
* streetName: "1 str"
* }
* })
* fistName
* }
*/
// e.g. something like ...
@GraphQLInputField(name = "address")
public void addAddressToUser(@GraphQLContext User user, @GraphQLArgument Address address) {
}
最佳答案
我现在想出了一种方法,您可以做到这一点,但这需要一些努力。
我正在使用 GraphQL-SPQR 0.9.8(我将在几天内发布)。您可以在 0.9.7 中实现相同的效果,只是不太符合人体工程学。
@Test
public void testSchema() {
GraphQLSchema schema = new GraphQLSchemaGenerator()
// Ignore extra fields (like "address") when deserializing
.withValueMapperFactory(JacksonValueMapperFactory.builder()
.withConfigurers(conf -> conf.getObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false))
.build())
.withInputFieldBuilders((conf, defaults) -> defaults.prepend(new UserInputBuilder(defaults.getFirstOfType(JacksonValueMapper.class))))
.withArgumentInjectors(new UserInjector())
.withOperationsFromSingleton(new TestService())
.generate();
GraphQL exe = GraphQL.newGraphQL(schema).build();
ExecutionResult result = exe.execute("{user(in: {name: \"A. Man\", address: {type: \"home\", street: {name: \"Fakestreet\", number: 123}}}) {name, street {number}}}");
}
public class TestService {
@GraphQLQuery //or mutation, no difference
public User user(User in) {
return in;
}
}
// Redefines how User objects are deserizalized
public static class UserInjector extends InputValueDeserializer {
@Override
public Object getArgumentValue(ArgumentInjectorParams params) {
User user = (User) super.getArgumentValue(params);
Map<?, ?> rawInput = (Map<?, ?>) params.getInput();
Address address = params.getResolutionEnvironment().valueMapper.fromInput(rawInput.get("address"), GenericTypeReflector.annotate(Address.class));
// Preprocess the address in any way you need, here I just extract the street
user.setStreet(address.getStreet());
return user;
}
@Override
public boolean supports(AnnotatedType type) {
return GenericTypeReflector.isSuperType(User.class, type.getType());
}
}
//Redefines the way User input type is mapped
public static class UserInputBuilder implements InputFieldBuilder {
private final InputFieldBuilder original;
public UserInputBuilder(InputFieldBuilder original) {
this.original = original;
}
@Override
public Set<InputField> getInputFields(InputFieldBuilderParams params) {
Set<InputField> fields = original.getInputFields(params);
// Add the extra "address" field you want
fields.add(new InputField("address", "User's home address", GenericTypeReflector.annotate(Address.class), null, null));
return fields;
}
@Override
public boolean supports(AnnotatedType type) {
return GenericTypeReflector.isSuperType(User.class, type.getType());
}
}
public class User {
private String name;
private Street street;
public User(String name, Street street) {
this.name = name;
this.street = street;
}
public String getName() {
return name;
}
public Street getStreet() {
return street;
}
@GraphQLIgnore //can be filtered out in a different way, without touching this class
public void setStreet(Street street) {
this.street = street;
}
}
public class Address {
private Street street;
private String type;
public Address(Street street, String type) {
this.street = street;
this.type = type;
}
public Street getStreet() {
return street;
}
public String getType() {
return type;
}
}
也就是说,在 Jackson(或 Gson,无论您使用什么)中注册自定义反序列化器并跳过自定义 ArgumentInjector
可能会更容易。
关于java - GraphQL SPQR 扩展输入对象的突变参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51873167/
有没有办法检索客户端在 GraphQL 查询中请求的字段列表? 假设我有以下类型: type Book { isbn: String title: String genre: String
我用 io.leangen.graphql.spqr库版本0.9.6我需要从 Query 中排除突变根节点进入文档。 我的 GraphQLController.kt看起来像这样: @RestContr
目前,我抛出 RuntimeException 来返回 GraphQL 验证错误。它的工作效果出奇的好,除了它在我的日志中抛出大量堆栈跟踪的可怕错误之外。 在这里您可以看到我正在检查提交的新用户注册突
使用 SQPR 构建 graphQL API。我有大量数据集合,想逐页加载数据。使用 SQPR 执行此操作的推荐方法是什么?从客户端(查询)来看它会是什么样子? 此外,请记住将 Apollo 客户端作
我graphql-spqr,java.util.Date被定义为标量。是否可以覆盖 java.util.Date 的序列化/反序列化以获得日期的不同字符串表示形式? 本文中提到的ScalarStrat
能够扩展现有类型是非常棒的,因为它允许代码模块化和权限分离。我找到了关于如何扩展查询中的对象输出的好例子(见下文),但没有好的方法来扩展给定对象的输入。 为了举例,假设我们有一个类User。 clas
如何使用 Graphql SPQR 库实现 GraphQL 的订阅功能? 最佳答案 一般来说,你只需要用 @GraphQLSubscription 注释一个方法。并确保该方法返回 org.reacti
我有以下带有自定义属性的数据模型: class Foo { private Long id; private Set attributes; } cla
我收到以下信息,但似乎找不到答案。 Error [ValidationError{validationErrorType=FieldUndefined, queryPath=[find_by_id],
我使用 GraphQL SPQR与实体 @Entity public class MyEntity { @Id @GeneratedValue(strategy = Generatio
我想在服务类中返回 JSON 文字 @GraphQLQuery(name = "renderUI", description = "Schema for your form") public Stri
我们正在将 graphql-spqr 和 graphql-spqr-spring-boot-starter 用于一个新项目(使用 Spring DataJPA、hibernate 等)。 我们有这样的
我正在尝试为我的 spring-boot/graphQL/SPQR 项目创建一些身份验证机制。我设法通过 @GraphQLRootContext 注释在单个服务方法上完成它: @GraphQLMuta
我注意到 GraphQL-SPQR 至少有几个可以配置的属性(例如 graphql.spqr.gui.enabled=true)。是否有配置指定使用 Gson 而不是 Jackson 进行对象序列化/
没有标准来表示NaN和 INFINITY Graphql 都不在以及 JSON . 在 JavaScript 中,JSON.stringify(0/0) 和 JSON.stringify(1/0) 将
我正在使用 graphql-spqr-spring-boot-starter库将现有的 Rest API 项目迁移到 GraphQL。我有一段下面的代码来获取当前的 HttpServletReques
我是一名优秀的程序员,十分优秀!