I have the following API specification in JSON format. I want to retrieve, using JSON path, those responses (200
, 401
, etc.) that return directly an array as a response. That is, [{}, {}, ...]
instead of {result: [{}, {}, ...]}
.
What I have been trying is:
$.paths.[*].[*].responses.[*].content.[?(@.type === 'array')]
But the main problem is that I get two results, nonetheless, it should return onle one (there's only one response being an array). It's a returning a more nested object inside the schema, that is also an array.
So my question is, how can I build a json path filter to fit my use case? I have tried more combinations but I cannot make it work.
If you go to a json path resolver and input my current expression, you will get these two results:
[
{
"type": "array",
"items": {
"type": "object",
"properties": {
"place_id": {
"type": "string",
"example": "ChIJ37HL3ry3t4kRv3YLbdhpWXE"
},
"name": {
"type": "string",
"example": "The White House"
},
"type": {
"type": "string",
"example": "tourist_attraction"
},
"formatted_address": {
"type": "string",
"example": "1600 Pennsylvania Avenue NW, Washington, DC 20500, United States"
},
"location": {
"type": "object",
"properties": {
"latitude": {
"type": "number",
"format": "float",
"example": 38.8976763,
"minimum": -90,
"maximum": 90
},
"longitude": {
"type": "number",
"format": "float",
"minimum": -180,
"maximum": 180,
"example": -77.0365298
}
}
}
}
}
},
{
"type": "array",
"minItems": 7,
"maxItems": 7,
"items": {
"type": "object",
"properties": {
"week_day": {
"type": "number",
"format": "int",
"minimum": 1,
"maximum": 7,
"example": 1
},
"zone_id": {
"type": "string",
"example": "Africa/Abidjan"
},
"start": {
"type": "string",
"pattern": "^\\d{4}$",
"example": "0100"
},
"end": {
"type": "string",
"pattern": "^\\d{4}$",
"example": "1630"
}
}
}
}
]
If you take a look, the first result is the only one I want, because is the schema of a response. The second one is just a nested structure in another part of the json, that also has a type
property set to array
.
So, the only valid result should be:
[
{
"type": "array",
"items": {
"type": "object",
"properties": {
"place_id": {
"type": "string",
"example": "ChIJ37HL3ry3t4kRv3YLbdhpWXE"
},
"name": {
"type": "string",
"example": "The White House"
},
"type": {
"type": "string",
"example": "tourist_attraction"
},
"formatted_address": {
"type": "string",
"example": "1600 Pennsylvania Avenue NW, Washington, DC 20500, United States"
},
"location": {
"type": "object",
"properties": {
"latitude": {
"type": "number",
"format": "float",
"example": 38.8976763,
"minimum": -90,
"maximum": 90
},
"longitude": {
"type": "number",
"format": "float",
"minimum": -180,
"maximum": 180,
"example": -77.0365298
}
}
}
}
}
}
]
Not relevant to the question I think, but this is to create a custom rule in spectral
for valdiating my API specs.
I'm not sure what the implementation you're using is doing, but having a .
before your bracketed segments is invalid and should be rejected.
Using this path
$.paths.*.*.responses.*.content.*[?(@.type == 'array')]
gets you what you're after.
(I also replaced the ===
with ==
because ===
isn't defined in JSON Path.)
$.foo[*]
is equivalent to $.foo.*
and returns every child under a foo
property. $.foo.[*]
(note the second .
) should be invalid.
Similarly, $.foo.[?(@.bar == 'value')]
is invalid. You need to drop that second .
to get $.foo[?(@.bar == 'value')]
.