Spring GraphQL-如何将JSON扩展标量映射到POJO属性



我正在使用Spring for GraphQL项目和GraphQL Java Extended Scalars项目来实现GraphQL API,以处理JSON属性,因为我拥有的数据属性是动态的,服务器不知道其结构。

这个JSON属性是突变输入中有效载荷的一部分,POJO看起来像这样:

@Accessors(fluent = true)
@Builder
@Data
@JsonDeserialize(builder = MutationInputModel.MutationInputModelBuilder.class)
public class MutationInputModel {
private JsonNode data;
...
}

如上所述,我使用Lombok注释进行反序列化和访问器生成。data属性是Jackson的JsonNode类型。

然而,当调用这种突变时,我得到了以下异常:

org.springframework.beans.BeanInstanceException:无法实例化[com.fasterxml.jjackson.databind.JsonNode]:它是抽象类吗?;嵌套异常是java.lang.InstructionException

在使用此库的先前GraphQL API实现中,相同的模型也可以正常工作。

我的问题是如何在POJO上正确设置JSON标量类型?我试过杰克逊的ObjectNodeMap<String, Object>,但都没有成功。

我最终实现了自己的自定义强制方法,所以我将在这里分享以供进一步参考:

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.Collections;
import java.util.Map;
import graphql.schema.Coercing;
import graphql.schema.CoercingParseLiteralException;
import graphql.schema.CoercingParseValueException;
import graphql.schema.CoercingSerializeException;
import static graphql.scalars.ExtendedScalars.Object;
/**
* Custom Coercing implementation in order to parse GQL Objects,
* which get mapped as LinkedHashMap instances by {@link graphql.scalars.object.ObjectScalar}
* into Jackson's JsonNode objects.
*/
public class JsonNodeCoercing implements Coercing<JsonNode, Object> {
private static final Coercing<?, ?> COERCING = Object.getCoercing();
private final ObjectMapper objectMapper;
public JsonNodeCoercing(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
@Override
public Object serialize(Object input) throws CoercingSerializeException {
return input;
}
@Override
public JsonNode parseValue(Object input) throws CoercingParseValueException {
return objectMapper.valueToTree(input);
}
@Override
public JsonNode parseLiteral(Object input) throws CoercingParseLiteralException {
return parseLiteral(input, Collections.emptyMap());
}
@Override
public JsonNode parseLiteral(Object input, Map<String, Object> variables) throws CoercingParseLiteralException {
return objectMapper.valueToTree(COERCING.parseLiteral(input, variables));
}
}

这就是标量bean配置的样子:

@Bean
public RuntimeWiringConfigurer runtimeWiringConfigurer(ObjectMapper objectMapper) {
GraphQLScalarType jsonScalarType = GraphQLScalarType.newScalar()
.name("JSON")
.description("A JSON scalar")
.coercing(new JsonNodeCoercing(objectMapper))
.build();
return wiringBuilder -> wiringBuilder
.scalar(jsonScalarType);
}

如果有人有其他/更简单的方法,请分享。

最新更新