当 GraphQL 字段类型为 String 但实际需返回结构化 JSON 对象时,GraphQL 会将整个对象序列化为带转义的字符串;解决方法是将字段改为自定义对象类型,让 GraphQL 引擎原生处理嵌套结构,从而输出纯净、可直接使用的 JSON 对象。
当 graphql 字段类型为 `string` 但实际需返回结构化 json 对象时,graphql 会将整个对象序列化为带转义的字符串;解决方法是将字段改为自定义对象类型,让 graphql 引擎原生处理嵌套结构,从而输出纯净、可直接使用的 json 对象。
在 GraphQL 中,字段类型决定其序列化行为。你当前的 schema 将 payload 定义为 String:
type StringApiResponse {
statusCode: String!
message: String!
timestamp: String!
payload: String # ❌ 问题根源:String 类型强制序列化为 JSON 字符串
}当你在 Java 后端传入一个已格式化的 JSON 字符串(如 "{"logo":"http://logo",...}"),GraphQL 执行器会将其再次 JSON 编码——即对引号、反斜杠等字符进行转义,最终导致前端收到的是双重编码的字符串(如 ""{ \"logo\": \"http://logo\" }""),必须手动 JSON.parse() 才能使用。
✅ 正确做法是:让 GraphQL 知道 payload 是一个结构化对象,而非原始字符串。需同步更新 schema 和 Java 数据模型:
1. 更新 GraphQL Schema(强类型定义)
type Query {
getValue: StringApiResponse
}
type StringApiResponse {
statusCode: String!
message: String!
timestamp: String!
payload: Payload # ✅ 改为自定义对象类型
}
type Payload {
logo: String!
name: LanguageSpecificContent!
copyrightText: LanguageSpecificContent!
help: String!
termsAndCondition: String!
}
type LanguageSpecificContent {
en: String!
ja: String!
}2. 更新 Java 数据类(保持类型一致)
public class Payload {
private String logo;
private LanguageSpecificContent name;
private LanguageSpecificContent copyrightText;
private String help;
private String termsAndCondition;
// getters & setters
}
public class LanguageSpecificContent {
private String en;
private String ja;
// getters & setters
}
public class StringApiResponse {
private String statusCode;
private String message;
private String timestamp;
private Payload payload; // ✅ 不再是 String,而是 Payload 实例
// getters & setters
}3. 调整 Resolver 逻辑(直接返回对象实例)
@QueryMapping(name = "getValue")
public StringApiResponse getValue() {
try {
// 假设 ValueService.getValue() 返回的是 Map<String, Object> 或 Payload 对象
Payload payload = ValueService.getPayload(); // ✅ 返回结构化对象,非 JSON 字符串
return StringApiResponse.builder()
.statusCode("S0000")
.message("Success")
.timestamp(Instant.now().toString())
.payload(payload) // 直接设值,无手动序列化
.build();
} catch (Exception e) {
throw new RuntimeException(e);
}
}4. 前端查询示例(精准按需获取字段)
{
getValue {
payload {
logo
name { en ja }
copyrightText { en ja }
help
termsAndCondition
}
}
}响应结果(无转义、可直接解构使用):
{
"data": {
"getValue": {
"payload": {
"logo": "http://logo",
"name": { "en": "AAA", "ja": "aaa" },
"copyrightText": { "en": "AAA", "ja": "aaa" },
"help": "http://help",
"termsAndCondition": "http://terms"
}
}
}
}⚠️ 关键注意事项:
- 切勿在 Java 层手动 new ObjectMapper().writeValueAsString(...):这会导致二次编码。GraphQL 已内置 JSON 序列化能力,只需提供 POJO 即可。
- 字段命名需严格匹配:Java 类属性名(或通过 @JsonProperty 注解)必须与 GraphQL 字段名一致。
- 空值处理:若 payload 可为空,schema 中应声明为 payload: Payload(非 Payload!),Java 端对应字段允许为 null。
- 性能与安全:结构化类型支持服务端字段裁剪(field selection)、静态验证和 IDE 自动补全,比 String 类型更健壮、可维护。
通过将 payload: String 升级为 payload: Payload,你不仅消除了恼人的转义字符,更践行了 GraphQL 的核心优势:声明式、类型安全、按需获取的 API 设计哲学。

















