当前位置: 首页 > 知识库问答 >
问题:

如何获得第一个元素时,过滤器在jsonpath?

欧阳正德
2023-03-14

因此,我正在研究以下json:

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

我想检索联系人的姓名类型为S,并且只检索第一个返回的联系人。

将jsonpath与此路径一起使用时,“$…contacts[?(@.contactType=='S')].name”始终返回字符串数组,因为筛选操作始终将结果作为数组返回。

所以我尝试了“$联系人[?(@.contactType='S')].name[0]”和“$联系人[?(@.contactType='S')][0]。name“,但运气不好。这些路径返回空结果。

所以我的问题是,在jsonpath中使用过滤器时,有没有办法只获取第一个元素。我目前正在使用jayway jsonpath v2。2.0.

共有2个答案

邵骁
2023-03-14

如果您在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)));

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

况繁
2023-03-14

我找到的最快解决方案就是将其与列表进行比较,所以在您的场景中如下所示:

.andExpect(jsonPath("$..contacts[?(@.contactType == 'S')].name", equalTo(Arrays.asList("Dante"))))

(假设你正在尝试比较一些测试结果当然)

 类似资料:
  • 问题内容: 我想知道是否可以获取列表或集合的第一个元素。使用哪种方法? 问题答案: Collection c; (这是获得a的“第一个”元素的最接近的位置。您应该意识到,它对于的大多数实现绝对没有任何意义。这可能对LinkedHashSet和TreeSet有意义,但对HashSet没有意义。)

  • 问题内容: 我有一个过滤器linkifyStuff,其中需要使用其他过滤器处理一些变量。我无法弄清楚从另一个调用一个过滤器的语法。 我了解过滤器链接-这不是我想要的。我想将过滤器应用于linkifyStuff过滤器中的局部变量,而不是其输入或输出。 我希望像下面这样工作,但是$ filter(’filtername’)显然不是正确的语法。 我可以为sanitizeStuff和sanitizeStu

  • 问题内容: 提取切片的最后一个元素的Go方法是什么? 上面的解决方案有效,但看起来很尴尬。 问题答案: 仅读取切片的最后一个元素: 要删除它: 参见此页面有关切片技巧

  • 额外的问题:我如何得到插值的结果,其中确切的时间戳的值是线性插值之间的两个周围的值?

  • 问题内容: 我有一个像下面这样的列表,其中第一个元素是id,另一个是字符串: 我只想从此元组列表创建ID列表,如下所示: 我将使用此列表,因此它必须是整数值的列表。 问题答案: