【问题标题】:How to define a type with list of java.util.objects in graphql-java如何在 graphql-java 中使用 java.util.objects 列表定义类型
【发布时间】:2019-12-03 23:14:14
【问题描述】:

我有一个模式,其中 json 可以有一个 Int 和 Strings 列表作为值。我想知道如何为我的场景定义一种解析器。

type Total {
  key: String
  values: [Object]
}

type Query {
  filter (key : String!) : Total
}

【问题讨论】:

    标签: graphql-java


    【解决方案1】:

    GraphQL 中没有通用对象的概念(如Java中的Object)。实际上,定义的类型如下(如here所述):

    1. Int:带符号的 32 位整数;
    2. Float:有符号双精度浮点值;
    3. 字符串:一个 UTF-8 字符序列;
    4. 布尔值:真或假;
    5. ID:ID 标量类型表示唯一标识符,通常用于重新获取对象或作为缓存的键。 ID类型的序列化方式与String相同;但是,将其定义为 ID 意味着它不适合人类阅读。

    您可以定义一个新的标量,但这意味着您必须自己定义如何对其进行序列化/反序列化和验证。它增加了更多的复杂性,但价值不大。而且,我觉得Graphql的strong类型完全丧失了这种特定类型。

    我认为您最好的选择是使用Interfaces。使用接口并使用包装器类型,您就可以对您正在谈论的这个通用对象进行建模,并帮助您编写如下模式:

    interface MyInterface {
        // must have a field at least (cannot be empty)
        id: ID!
    }
    
    type MyInt implements MyInteface {
        // Inherited by MyInterface
        id: ID!
    
        myIntValue: Int
    }
    
    type MyString implements MyInteface {
        // Inherited by MyInterface
        id: ID!
    
        myStringValue: String
    }
    
    type Total {
        key : String
        values: [MyInterface]
    }
    
    type Query {
        filter(key: String!) : Total
    }
    

    注意:请注意界面不能为空(无字段)。为此,我添加了一个由实现随机生成的 ID 字段。

    使用这样的架构,我们可以执行如下查询:

    filter("someFilter") {
        key
        values {
            ... on MyString {
                myStringValue
            }
            ... on MyInt {
                myIntValue
            }
        }
    }
    

    为此,您需要定义一个 TypeResolver,如下所示:

    private class MyInterfaceTypeResolver implements TypeResolver {
        @Override
        public GraphQLObjectType getType(TypeResolutionEnvironment env) {
            Object obj = env.getObject();
    
            if (obj instanceOf MyInt) {
                env.getSchema().getObjectType("MyInt");
            } else if (obj instanceOf MyString) {
                env.getSchema().getObjectType("MyString");
            } else {
                return null;
            }
        }
    }
    

    具有以下 Java 类型定义:

    abstract class MyInterface {
        private String id;
    
        public MyInterface() {
            // Generated just to avoid empty graphql interface
            id = UUID.randomUUID().toString();
        }
    
        public String getId() {
            return id;
        }
    }
    
    class MyInt extends MyInterface {
        private Integer myIntValue;
    
        public MyInt(Integer myInt) {
            super();
            this.myIntValue= myInt;
        }
    
        public Integer getMyIntValue() {
            return myInt;
        }
    }
    
    class MyString extends MyInterface {
        private String myStringValue;
    
        public MyString (String myString) {
            super();
            this.myStringValue= myString;
        }
    
        public String getMyStringValue() {
            return myStringValue;
        }
    }
    
    

    假设您要表示以下 Json {"key": "myKey", "values":[12,"String1", 1, "String2"]},给定我们之前的模型和查询,它将表示为:

    {
       "data": {
           "filter": {
               "key": "myKey",
               "values" : [
                   {
                       "myIntValue": 12
                   },
                   {
                       "myStringValue": "String1"
                   },
                   {
                       "myIntValue": 1
                   },
                   {
                       "myStringValue": "String2"
                   }
               ]
           }
       }
    }
    

    最后,你可以有多个属性,每个类型一个,例如:

    type Total {
        key : String
        valuesInt: [Int]
        valuesString: [String]
    }
    
    type Query {
        filter(key: String!) : Total
    }
    

    【讨论】:

    • 能否请您提供解析器。我不确定如何使用界面,它将能够呈现像这样的东西 { key : "Tot", values : ["Value1", 234,143, "Value2" ] }
    • 更新了一个例子
    • @D.Lawrence 虽然这种方法适用于 Type,但我要补充的是 Input 不支持接口。
    • 知道了。谢谢!!
    猜你喜欢
    • 2020-04-20
    • 2021-01-09
    • 2020-03-13
    • 2021-08-31
    • 2020-12-19
    • 2021-11-20
    • 2020-09-29
    • 2019-01-11
    • 2019-05-30
    相关资源
    最近更新 更多