繁体   English   中英

返回 HashMap<string, object> 来自 GraphQL-Java</string,>

[英]Return HashMap<String, Object> from GraphQL-Java

我尝试了几个变体,但没有运气在 GraphQL 中返回 map。 所以我有以下两个对象:

public class Customer {

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

public class Person {

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

我的架构如下所示:

type Customer {
   name: String!
   age:  String!
}

type Person {
  type: String!
  customers: [Customer!] // Here I tried all combination but had no luck, is there a Map type support for GQL?
}

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

非常感谢!

正如您自己指出的,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 标量,因为它归结为填充任意 JSON 结构并将其视为标量。 同样的方法可以在 Java 中实现。 graphql-java 现在有一个 扩展标量项目。 这是他们的ObjectScalar (别名为JsonScalar )实现。

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

事实上,您可以决定将任何地图(嗯,实际上是任何类型,但这没有用)表示为 JSON 标量。

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

scalar ObjectScalar

从好的方面来说,您现在可以准确地保持任何动态结构的形状。 不利的一面是,由于它是标量,因此无法进行子选择,并且您无法提前获取所有内容,而事先不知道里面有什么。

GraphQL 中没有地图类型( GitHub 上的讨论)。

另一种方法是将有customersListCustomer小号

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;
}

架构将大部分保持不变。

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

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

我们有三个选择:

1) 作为 JSON 字符串返回 2) 使用 GraphQL 自定义标量类型 3) 作为键值对列表返回

https://www.baeldung.com/java-graphql-return-map

以防万一 - 您始终可以将地图对象表示为 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 字符串一样与客户进行操作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM