如何将第三方GraphQL响应解析并编组为Java POJO?
如何将第三方GraphQL响应编组为POJO?
我刚接触GraphQL,正在对接第三方外部服务器的GraphQL接口——已经成功发送查询并收到响应,但卡在了把响应转换成POJO或者ArrayList<POJO>这一步,而且第三方没提供GraphQL schema文件。想请教下怎么处理这个问题,有没有合适的Java库推荐?
我的GraphQL查询
query Photos($first: Int!, $propertyId: String) { viewer { content { contentLists(first: $first, property_id: $propertyId, contentListType: IMAGE, publishState: PUBLISHED, orderBy: originalPublishDate, orderByDirection: DESC) { edges { node { id title caption originalPublishDate lastModifiedDate contents(first: $first) { edges { node { id title caption type ... on Image { asset { createdDate lastModifiedDate id url title height width } } } } } } } } } } }
查询变量
{ "propertyId" : "23456832-7862-5679-4342-415f32385830", "first": 20 }
发送请求的Java代码
HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); headers.set("Authorization", "Bearer "+accessToken); HttpEntity<String> entity = new HttpEntity<String>(request,headers); String response = restTemplate.postForObject(EXTERNAL_URL, entity, String.class);
收到的响应
{ "data": { "viewer": { "content": { "contentLists": { "edges": [ { "node": { "id": "3510e8f7-452s-f531-43b0-ac36ba979e5a9f4m", "title": "Homer Simpson goes Camping", "caption": "Homer Simpson goes Camping", "originalPublishDate": "2018-02-18T03:31:56.352Z", "lastModifiedDate": "2018-02-18T03:32:13.530Z", "contents": { "edges": [ { "node": { "id": "3506d951-1332-86fg-42bc-b11183db50394f40", "title": "No Title", "caption": "", "type": "IMAGE", "asset": { "createdDate": "2018-02-18T03:31:38.406Z", "lastModifiedDate": "2018-02-18T03:31:38.991Z", "id": "65037262-7169-7065-7861-7035676a6f65323467617866", "url": "", "title": "No Title", "height": null, "width": null } } } ] } } } ] } } } } }
当前使用的依赖
<dependency> <groupId>com.graphql-java</groupId> <artifactId>graphql-java</artifactId> <version>8.0</version> </dependency> <dependency> <groupId>com.graphql-java</groupId> <artifactId>graphql-java-tools</artifactId> <version>5.0.0</version> </dependency>
解决方案:用通用JSON解析库处理(无需schema)
因为第三方没有提供GraphQL schema,所以依赖schema的工具(比如graphql-java-tools)派不上用场。GraphQL响应本质就是标准JSON,所以用Jackson或Gson这类通用JSON解析库是最直接的方案,下面分两种场景说明:
1. 类型安全:手动创建POJO + Jackson反序列化
这种方案适合长期维护的代码,通过创建和响应结构匹配的POJO类,实现类型安全的解析。
步骤1:添加Jackson依赖(如果项目里还没有)
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.15.2</version> <!-- 建议使用最新稳定版 --> </dependency> <!-- 如果用Java 8+的日期时间API,添加这个模块 --> <dependency> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-jsr310</artifactId> <version>2.15.2</version> </dependency>
步骤2:创建匹配响应结构的POJO类
根据你收到的JSON结构,逐层创建嵌套类(字段名要和JSON一致,或者用@JsonProperty映射):
// 根响应类 public class GraphQLResponse { private Data data; // Getters & Setters } public class Data { private Viewer viewer; // Getters & Setters } public class Viewer { private Content content; // Getters & Setters } public class Content { private ContentLists contentLists; // Getters & Setters } public class ContentLists { private List<ContentListEdge> edges; // Getters & Setters } public class ContentListEdge { private ContentListNode node; // Getters & Setters } public class ContentListNode { private String id; private String title; private String caption; private LocalDateTime originalPublishDate; // 用Java 8 LocalDateTime private LocalDateTime lastModifiedDate; private Contents contents; // Getters & Setters } public class Contents { private List<ContentEdge> edges; // Getters & Setters } public class ContentEdge { private ImageContentNode node; // Getters & Setters } public class ImageContentNode { private String id; private String title; private String caption; private String type; private Asset asset; // Getters & Setters } public class Asset { private LocalDateTime createdDate; private LocalDateTime lastModifiedDate; private String id; private String url; private String title; private Integer height; private Integer width; // Getters & Setters }
步骤3:反序列化响应字符串
ObjectMapper objectMapper = new ObjectMapper(); // 配置支持Java 8日期时间 objectMapper.registerModule(new JavaTimeModule()); objectMapper.configure(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE, false); // 忽略未知字段(防止第三方更新接口加字段导致解析失败) objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); // 把响应字符串转成POJO GraphQLResponse graphQLResponse = objectMapper.readValue(response, GraphQLResponse.class); // 提取所有图片节点到ArrayList List<ImageContentNode> imageList = new ArrayList<>(); graphQLResponse.getData().getViewer().getContent().getContentLists().getEdges().forEach(listEdge -> { listEdge.getNode().getContents().getEdges().forEach(contentEdge -> { imageList.add(contentEdge.getNode()); }); });
2. 灵活解析:用JsonNode动态遍历(无需POJO)
如果只是临时处理数据,不想写大量POJO,可以用Jackson的JsonNode直接遍历JSON结构:
ObjectMapper objectMapper = new ObjectMapper(); JsonNode rootNode = objectMapper.readTree(response); // 逐层遍历到内容节点 JsonNode contentListEdges = rootNode.path("data") .path("viewer") .path("content") .path("contentLists") .path("edges"); for (JsonNode listEdge : contentListEdges) { JsonNode contentListNode = listEdge.path("node"); String listTitle = contentListNode.path("title").asText(); // 遍历图片内容 JsonNode contentEdges = contentListNode.path("contents").path("edges"); for (JsonNode contentEdge : contentEdges) { JsonNode imageNode = contentEdge.path("node"); String imageUrl = imageNode.path("asset").path("url").asText(); // 按需处理数据 } }
关于GraphQL专用库的说明
因为第三方没有提供schema,graphql-java-tools这类依赖schema生成代码的工具就不适用了。而graphql-java本身主要用于构建GraphQL服务器或执行查询,不是用来解析响应的。所以通用JSON解析库(Jackson/Gson)是最适合的选择,它们足够灵活,不需要依赖schema就能处理GraphQL响应。
内容的提问来源于stack exchange,提问作者PacificNW_Lover
相关产品推荐
相关产品推荐

