首页 > 解决方案 > JsonPropertyAccessor 的选择器访问问题

问题描述

在使用 org.springframework.expression.spel.standard.SpelExpressionParser 将 JsonNode 访问到 Spring Boot 2.2.4 服务时,我遇到了一个问题。我可以用下面的例子来描述这个问题:

给定 Json 作为 StandardEvaluationContext 中的根对象:

{"property":[{"name":"value1"},{"name":"value2"}]}

下面带有选择器的 spring 表达式语言值返回value1没有问题:

property.^[name != null].name

但是下面的这个选择器返回null而不是value1

property.^[name == 'value1'].name

任何想法 ?

编辑:

这是一个主要的方法类示例:

import java.util.List;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.integration.json.JsonPropertyAccessor;

public class TestJsonAccessor {

    public static void main(String[] args) throws JsonMappingException, JsonProcessingException {
        StandardEvaluationContext context = new StandardEvaluationContext();
        context.setPropertyAccessors(List.of(new JsonPropertyAccessor()));
        context.setRootObject(new ObjectMapper().readTree("{\"property\":[{\"name\":\"value1\"},{\"name\":\"value2\"}]}"));

        SpelExpressionParser parser = new SpelExpressionParser();

        System.out.println(parser.parseExpression("property.^[name != null].name").getValue(context));
        System.out.println(parser.parseExpression("property.^[name == 'value1'].name").getValue(context));
    }
}

在打印的控制台中:

value1
Exception in thread "main" org.springframework.expression.spel.SpelEvaluationException: EL1007E: Property or field 'name' cannot be found on null
    at org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:213)
    at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:104)
    at org.springframework.expression.spel.ast.PropertyOrFieldReference.access$000(PropertyOrFieldReference.java:51)
    at org.springframework.expression.spel.ast.PropertyOrFieldReference$AccessorLValue.getValue(PropertyOrFieldReference.java:406)
    at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:92)
    at org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.java:112)
    at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:272)
    at TestJsonAccessor.main(TestJsonAccessor.java:20)

标签: jsonspring-integrationspring-el

解决方案


问题出在这里:name == 'value1'。这name不是要比较的纯文本 - 它是一个ToStringFriendlyJsonNode并且要使其与该equal运算符一起工作,您需要将其作为字符串。因此像这样:

property.^[name.toString() == 'value1'].name

实现目标还有另一种更长的方法:

property.^[name.getTarget().asText() == 'value1'].name

它的JsonPropertyAccessor目的是使最终结果对最终用户友好。在中间它仍然是我们需要处理的一些 JSON 对象。


推荐阅读