从GraphQL-Java返回HashMap <string,object =“”>

时间:2017-12-06 12:41:39

标签: java graphql graphql-java

我尝试了一些变体,没有运气在GraphQL中返回地图。所以我有以下两个对象:

invalid=True
def start():
    x=input('Enter the Keyword:')
    if ("m" == x) or ("M"==x):
        print('Correct!')
    elif x!='m' or x!='M':
        print('Invalid Input.')
        invalid=False
    while invalid:
        start()

我的架构如下所示:

public class Customer {

    private String name, age;
    // getters & setters
}

public class Person {

   private String type;
   private Map<String, Customer> customers;
   // getters & setters
}

有人可以告诉我如何实现这一点,以便GraphQL神奇地处理这个或另一种方法。

非常感谢!

3 个答案:

答案 0 :(得分:5)

正如您自己所说,GraphQL中没有地图类型,主要是因为地图基本上是无类型数据(或具有动态结构的数据),因此不能很好地转换为GraphQL期望的静态类型。不过,你有几个选择。

1)您可以更改值类型,使其包含密钥,然后放弃地图并使用列表。这是您在自己的答案中采用的方法。我不会在这里详细说明,因为你已经举例说明了它。

2)只要知道了键和值Java类型(而不是Object),就可以将地图视为键值对列表。您可以创建一个类型来表示该对:

type Person {
  type: String!
  customers: [CustomerEntry!]
}

type CustomerEntry {
  key: String!
  value: Customer!
}

在不利方面,你现在有更丑陋的疑问:

{
   person {
     type
     customers {
       key
       value {
         name
       }
     }
   }
}

在好的方面,你保持类型安全和(大部分)语义。可以将这种方法嵌套到例如代表Map<String, Map<Long, Customer>>

3)如果您有一个完全未知的类型,即Object,唯一的选择是将其视为一个复杂的标量。在JavaScript中,这种方法被称为JSON scalar,因为它归结为填充任意JSON结构并将其视为标量。可以用Java实现相同的方法。 graphql-java现在有一个extended scalars的项目。这是他们的ObjectScalar(别名为JsonScalar)实现。

现在,如果您想表示Map<String, Object>之类的类型,您可以选择使用上面的键值对方法来表示它,只有值类型是JSON标量,或者您可以表示整个地图作为JSON标量。

事实上,你可以决定代表任何地图(嗯,任何类型,但这没用),作为JSON标量。

type MapEntry {
  key: String!
  value: [ObjectScalar!]
}

scalar ObjectScalar

在好的方面,您现在可以准确地保留任何动态结构的形状。 在缺点方面,因为它是一个标量,所以不可能进行子选择,并且你不知道所有内容,而不知道内部是什么。

答案 1 :(得分:2)

GraphQL中没有地图类型(Discussion on GitHub)。

另一种方法是将customers作为List Customer的<{1}}

public class Person {
   private String type;
   private List<Customer> customers;
}

并在Customer

中包含地图的键
public class Customer {
    private String key; // or another meaningful name
    private String name, age;
}

Schema大部分都保持不变。

type Customer {
   key: String! // or another meaningful name
   name: String!
   age: String!
}

type Person {
  type: String!
  customers: [Customer!]!
}

答案 2 :(得分:0)

以防万一-您始终可以将地图对象表示为JSON字符串(对我而言,这很有用)。

public class Person {

    private String type;
    private Map<String, Customer> customers;
    // getters & setters
}

将会

type Person {
  type: String!
  customers: String!
}

此后,别忘了添加数据获取程序以将其转换为JSON。

public DataFetcher<String> fetchCustomers() {
        return environment -> {
            Person person = environment.getSource();
            try {
                ObjectMapper objectMapper = new ObjectMapper();
                return objectMapper.writeValueAsString(person.getCustomers());
            } catch (JsonProcessingException e) {
                log.error("There was a problem fetching the person!");
                throw new RuntimeException(e);
            }
        };
    }

它将返回:

"person": {
    "type": "2",
    "customers": "{\"VIP\":{\"name\":\"John\",\"age\":\"19\"},\"Platinum VIP\":{\"name\":\"Peter\",\"age\":\"65\"}}"
  }

此后,您可以像处理客户端中的典型JSON字符串一样与客户合作。