Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jayway JsonPath filter json to get distinct values

Tags:

json

jsonpath

Do you know if there is a filter function that will get me unique (distinct) values from a json file with Jayway JsonPath?

I have a simple json

{  "services": [
{
  "value": "ThingA",
  "functions": [
    {
      "value": "1"
    },
    {
      "value": "2"
    },
    {
      "value": "3"
    }
  ]
},
{
  "value": "ThingB",
  "functions": [
    {
      "value": "4"
    },
    {
      "value": "1"
    },
    {
      "value": "6"
    }
  ]
}]}

and I need to get all the distinct functions values for ThingA and ThingB. For now I filter with

$.services[?(@.value in ['thingA','thingB'])].functions[*][*]

but this is giving me the values 1,2,3,4,1,6 (so 1 is repeated twice).

like image 475
gospodin Avatar asked Sep 14 '25 20:09

gospodin


2 Answers

You could perhaps use a com.jayway.jsonpath.Predicate to filter for distinct values, like this:

@Test
public void canExtractDistinctValues() {
    List<String> read = JsonPath.parse(... your json ...).read("$.services[?(@.value in ['ThingA','ThingB'])].functions[?].value", List.class,
            new DistinctPredicate("value"));

    assertThat(read.size(), is(5));
    assertThat(read, hasItem("1"));
    assertThat(read, hasItem("2"));
    assertThat(read, hasItem("3"));
    assertThat(read, hasItem("4"));
    assertThat(read, hasItem("6"));
}

private class DistinctPredicate implements Predicate {
    private final String fieldName;
    private final Set distinctValues;

    public DistinctPredicate(String fieldName) {
        this.fieldName = fieldName;
        this.distinctValues = Sets.newHashSet();
    }

    @Override
    public boolean apply(Predicate.PredicateContext context) {
        String value = context.item(Map.class).get(fieldName).toString();
        if (distinctValues.contains(value)) {
            return false;
        } else {
            distinctValues.add(value);
            return true;
        }
    }
}
like image 174
glytching Avatar answered Sep 16 '25 10:09

glytching


you can use .distinct() as something like:

Arrays.stream(JsonPath
   .parse(jsonString)
   .read(jsonPath, String[].class))
   .distinct()
   .collect(Collectors.toList())
   ;
like image 25
Michael Hegner Avatar answered Sep 16 '25 10:09

Michael Hegner