A tricky difference between JSON(Path) and XML(Path)

A tricky difference between JSON(Path) and XML(Path)

Developers and testers familiar with XPath may become frustrated when trying to make more complex JSONPath expressions. Also, sometimes people get surprised that their JSONPath was working some time ago but suddenly stopped.

XML and JSON are tree-like structures, so querying should be very similar. Even more, JSONPath is usually considered to be the XPath for JSON. So, what's the difference?

Selecting nodes in XPath

First, let's try to find mobile phone contacts in the following XML with XPath:

<?xml version="1.0" encoding="UTF-8"?
<purchases>
   <customer>
      <firstName>John</firstName>
      <lastName>Brown</lastName>
      <age>26</age>
      <address>
         <streetAddress>Tibera street 23</streetAddress>
         <city>Rome</city>
         <postalCode>12365</postalCode>
      </address>
      <phone>
         <type>home</type>
         <number>0123-4567-8888</number>
      </phone>
   </customer>
   <customer>
      <firstName>Anne</firstName>
      <lastName>Fox</lastName>
      <age>25</age>
      <address>
         <streetAddress>Flower street 206</streetAddress>
         <city>Glasgow</city>
         <postalCode>98653</postalCode>
      </address>
      <phone>
         <type>mobile</type>
         <number>+41-569-9563</number>
      </phone>
   </customer>
</purchases>>        

Using this XPath expression, we get all phone contacts:

//customer/phone        

If we decide to get the mobile phones only, we apply the condition:

//customer/phone[type='mobile']        

Trying the same with JSONPath.

Now, let's move on to JSON and JSONPath:

{
  "customers": [
    {
      "firstName": "John",
      "lastName": "Brown",
      "age": 26,
      "address": {
        "streetAddress": "Tibera street 23",
        "city": "Rome",
        "postalCode": "12365"
      },
      "phone": {
        "type": "home",
        "number": "0123-4567-8888"
      }
    },
    {
      "firstName": "Anne",
      "lastName": "Fox",
      "age": 25,
      "address": {
        "streetAddress": "Flower street 206",
        "city": "Glasgow",
        "postalCode": "98653"
      },
      "phone": {
        "type": "mobile",
        "number": "+41-569-9563"
      }
    }
  ]
}        

JSONPath syntax is a bit different but getting all phones is still pretty straightforward:

$..phone        

Now, how to pick the mobile phones only. Any guess? Applying a condition? OK, let's give it a try:

$..phone[?(@.type=='mobile')]        

Does that work? Yes, it works! No, it does NOT! Give it a try in online JSOPath tools, e.g., https://jsonpath.com or https://jsonpath.herokuapp.com/. If you check the second app, you will find that the JSONPath expression works in Jayway but not in the Goessner implementation (see screenshot below).

Different results in JSONPath evaluators

What's wrong with my expression? The syntax seems all right. The issue is that JSONPath treats the square brackets [] operator differently than XPath. In XPath, you could apply the condition on any XML node. However, in JSONPath, you can apply the [] operator only ARRAYS. In our example, we have an array customers:

$..customers[?(@.phone.type=='mobile')].phone        

What does that mean:

  • select the customer with mobile phone: customers[?(@.phone.type=='mobile')]
  • take his phone: .phone

Try the expression above in JSONPath evaluators. It should work fine.

Conclusion

In complex JSON documents, we need to put lengthy condition inside [] (path + condition) and then repeat part of it (path) just behind the brackets.

Some JSONPath implementations followed XPath and allowed to use the [] operator with a condition on any JSON element. However, the array-only usage took over.

I assume the rationale is that JSON contains arrays; thus, JSONPath needs an array operator to select a specific item. On the other hand, XML does not distinguish between arrays and other nodes and allows repeating the elements of the same type without making an array.

JSONPath follows many XPath principles, allowing the selection anywhere would be more intuitive. Maybe a lesson learned for future designs: if you apply a well-known pattern, use it as much as possible, without unnecessary modifications.

Discussion

You are welcome to share your opinions and experience in the discussion. Also, if you find anything which needs to be fixed, let me know.

Karel@apimate.eu, https://apimate.eu

$.customers..[?(@.age > 25)].firstName  very nice just like selenium 4 relativelocators

Like
Reply

To view or add a comment, sign in

More articles by Karel Husa

  • Fix XML content-type recognition in SoapUI 5.8.0

    The latest open-source SoapUI 5.8.

    5 Comments
  • SoapUI: What if REST API changes?

    There's a new REST API, version 1.0.

    2 Comments
  • Test cases in Bruno, part 1

    Most 📍API operations are not isolated. We usually have an API use case where we call multiple operations in the proper…

    3 Comments
  • Bruno, helper dog for your APIs

    I love visual API tools. I have been playing with APIs for 20 years.

    12 Comments
  • SOAP in a REST room

    Recently, one of the API consumers asked me for an API definition. I told him the API is a SOAP service and offered to…

  • How GPT talks to APIs

    OpenAI GPTs are able to integrate with your favorite APIs via Actions. The question is, how to tell GPT enough about…

    3 Comments
  • Troubleshooting GPT Actions: Path parameters

    OpenAI Actions is a powerful tool to connect GPTs with any other applications via APIs. Sometimes the integration is…

    1 Comment
  • Postman jailed in an internal network

    Postman is a cool tool to work with APIs: publishing API definitions, testing APIs. creating virtual mock APIs or…

    2 Comments
  • SoapUI hack for OpenAPI 3

    SoapUI had been a leading testing tool and in many places it's still popular and in use. One of the main pain-points…

    4 Comments
  • SoapUI is over. What next?

    SoapUI has been a top-notch API exploratory and integration testing tool for almost 20 years. It is simple and friendly…

    3 Comments

Others also viewed

Explore content categories