在jsonpath中过滤时如何获取第一个元素?

时间:2017-01-08 04:48:11

标签: java jsonpath

所以我正在研究下面的json:

{
   "id": "",
   "owner": "some dude",
   "metaData": {
      "request": {
         "ref": null,
         "contacts":[
            {
               "email": null,
               "name": null,
               "contactType": "R"
            },
            {
               "email": null,
               "name": "Dante",
               "contactType": "S"
            }
         ]
      }
   }
}

我想要检索联系人类型name的{​​{1}},并且只检索返回的第一个联系人。

将jsonpath与此路径一起使用S始终返回一个字符串数组,因为过滤操作始终将结果作为数组返回。

所以我尝试了"$..contacts[?(@.contactType == 'S')].name""$..contacts[?(@.contactType == 'S')].name[0]",但没有运气。那些路径返回空结果。

所以我的问题是,在jsonpath中使用过滤器时,是否有任何方法只能得到第一个元素。我目前正在使用jayway jsonpath v2.2.0。

2 个答案:

答案 0 :(得分:3)

我找到的最快的解决方案就是将它与列表进行比较,所以在你的场景中这样:

Runnable runnable = new Demo();

(假设你试图在测试中比较某些结果)

答案 1 :(得分:1)

如果你在spring-test中使用带有MockMvc类的jsonpath,那么你可以写下面的虚拟匹配器:

import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.core.IsEqual;

import net.minidev.json.JSONArray;

public class FirstMatcher<T> extends BaseMatcher<T> {

    private final Matcher<?> matcher;

    public static <T> FirstMatcher<T> matcher(Matcher<T> matcher) {
        return new FirstMatcher<T>(matcher);
    }

    public static FirstMatcher<Object> value(Object value) {
        return new FirstMatcher<Object>(value);
    }

    public FirstMatcher(Matcher<T> matcher) {
        this.matcher = matcher;
    }

    public FirstMatcher(Object value) {
        this.matcher = new IsEqual<Object>(value); 
    }

    @Override
    public void describeTo(Description description) {
        description.appendText("first matcher");
    }

    @Override
    public boolean matches(Object item) {
        if (!(item instanceof JSONArray)) {
            return false;
        }

        JSONArray array = (JSONArray)item;
        if (array.isEmpty()) {
            return false;
        }

        Object obj = array.get(0);
        return matcher.matches(obj);
    }

}

并使用以下方式:

mockMvc.
    perform(get(url).
            accept(MediaType.APPLICATION_JSON).accept(MediaType.TEXT_PLAIN).accept(MediaType.ALL)).
    andExpect(status().isOk()).
    andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)).
    andExpect(jsonPath("$.properties[?(@.propertyName == 'name1')].description").value(FirstMatcher.matcher(IsNull.nullValue()))).
    andExpect(jsonPath("$.properties[?(@.propertyName == 'name2')].required").value(FirstMatcher.value(true)));

P.S。由于net.minidev.json.JSONArray是java.util.List的子类,因此可以转换为List甚至是Iterable而不是net.minidev.json.JSONArray。 :)