{ Community }
  • Academy
  • Docs
  • Developers
  • Resources
    • Community Articles
    • Apigee on GitHub
    • Code Samples
    • Videos & eBooks
    • Accelerator Methodology
  • Support
  • Ask a Question
  • Spaces
    • Product Announcements
    • General
    • Edge/API Management
    • Developer Portal (Drupal-based)
    • Developer Portal (Integrated)
    • API Design
    • APIM on Istio
    • Extensions
    • Business of APIs
    • Academy/Certification
    • Adapter for Envoy
    • Analytics
    • Events
    • Hybrid
    • Integration (AWS, PCF, Etc.)
    • Microgateway
    • Monetization
    • Private Cloud Deployment
    • 日本語コミュニティ
    • Insights
    • IoT Apigee Link
    • BaaS/Usergrid
    • BaaS Transition/Migration
    • Apigee-127
    • New Customers
    • Topics
    • Questions
    • Articles
    • Ideas
    • Leaderboard
    • Badges
  • Log in
  • Sign up

Get answers, ideas, and support from the Apigee Community

  • Home /
  • Edge/API Management /
avatar image
8

Converting between XML and JSON with Apigee Edge: what you need to know  

  • Export to PDF
Mike Dunker @Google   created · Mar 07, 2015 at 08:36 AM · 59.1k Views · edited · Sep 24, 2018 at 09:14 PM

Apigee Edge can do lots of things. One of those things is to dynamically convert between an XML payload to a JSON "equivalent". Common reasons for doing this:

  • creating a RESTful facade for an existing SOAP service (via a SOAP to REST proxy within Apigee)
  • providing content-negotiation in the proxy layer - eg let the caller or client specify whether it wants XML or JSON, and the proxy layer (Apigee Edge) can formats it correctly. The backend (upstream) need not be aware.

There may be other reason as well. Regardless of your reasoning, when converting between XML and JSON, you need to be aware: there are significant differences between XML and JSON, as well as limitations of the XMLToJSON and JSONToXML policies that you should understand. I'll explain those, and then I will present a couple of working proxy solutions that implement SOAP to REST conversions without requiring lots of custom code.

Data Types

JSON:

{ "myNum": 9, "myBool": true, "myStr": "val",
  "myEmptyObject": {}, "myEmptyStr": "", "myNull": null }

JSON is strongly typed. Numbers, booleans, strings, empty strings, empty objects and nulls can all be clearly specified.

XML:

<StringOrNumber>12345</StringOrNumber>
<StringOrBoolean>false</StringOrBoolean>
<EmptyObjectOrEmptyStringOrNull></EmptyObjectOrEmptyStringOrNull>

Unless you are using XML Schema Definitions (XSDs), XML does not clearly delineate between data types. Chances are good that if the value of an element is "false", the type is boolean. However, it could also be a string (<TeethType>false</TeethType>).

Similarly, most ZIP codes look like numbers in XML. However, the standard data type to use for a ZIP code is string, because you can have ZIP codes with leading zeroes or ZIP+4 formats. Without the context of what the field means, an automatic converter cannot convert both <ZIPCode> (string) and <Age> (number) correctly.

Empty strings ( "" ), empty objects ( { } ) and nulls also look identical in XML.

Conversion:

JSONToXML will handle data conversions correctly, since the data type is just basically stripped.

XMLToJSON provides configuration options to choose whether to detect numbers, booleans and nulls. Where necessary, you might need to tweak data types post-conversion where the types may be ambiguous.

Arrays

                             JSON                       XML
  
Empty array:                  []                   -nothing in the XML-

Single item array:    [ { "name": "val" } ]          <name>val</name>

Multiple item array:    [ "Arm", "Leg" ]      <item>Arm</item><item>Leg</item>

JSON arrays are specified using square brackets.

XML arrays are represented by repeating an element name multiple times.

XML arrays can also be represented as zero or more elements of the same name wrapped in another element:

<Languages>
  <item>JavaScript</item>
  <item>Java</item>
  <item>Python</item>
</Languages>

Conversion:

JSONToXML can generally convert arrays correctly.

For wrapped XML arrays, the XMLToJSON conversion looks a bit strange:

{"Languages":{"item":["JavaScript","Java","Python"]}}

For non-wrapped arrays, XMLToJSON has difficulty converting zero element arrays. There are no elements in the XML, so there won't be anything in the JSON.

Single element arrays also are a problem: they look identical to a single object, so the JSON will show an object instead of an item in an array.

Make sure you fix converted array and data type idiosyncrasies -- don't force your app developers to deal with inconsistent types.

Root Elements

XML requires a single named root element. All other elements must exist within this element.

JSON does not require a root element: the top level is generally an unnamed object or array.

XMLToJSON will convert as expected, but a dummy root element will sometimes be created for the other direction (shown are the conversions with the default JSONToXML settings):

[ "abc", "def" ]        ->  <Array><Item>abc</Item><Item>def</Item></Array>

{ "a": "abc" }          ->  <a>abc</a>                 (only one item in object)

{ "a": "abc", "b": 14 } ->  <Root><a>abc</a><b>14</b></Root>    (multiple items)

Namespaces and Attributes

XML has namespaces and attributes, JSON does not. If you need those when converting from XML to JSON (you often do need at least the attributes), they need to be put somewhere else in the JSON payload. XMLToJSON allows you to specify where these will go.

Multi-line

XML is allowed to span multiple lines. JSON is also allowed to be multi-line (see ECMA-404 from Oct 2013), but some legacy JSON parsers do not support multi-line JSON. If you need to support these, consider returning your JSON on a single line. However, you should always accept JSON that spans multiple lines.

Converting between formats

When a payload to be converted is simple and predictable, you can often use ExtractVariables to get data out of the input payload and AssignMessage to build the converted payload. When this is easy, this will be the most efficient solution. This is often the solution for SOAP requests, even when the corresponding SOAP responses are very complex.

When you have more complex payloads to convert, especially SOAP responses and payloads with arrays, you'll generally need a different solution that includes XMLToJSON and JSONToXML.

Your first inclination might be to use custom JavaScript code to tweak the payload before the JSONToXML conversion or after the XMLToJSON conversion. This becomes untenable as the number of different payloads/SOAP responses grows.

When I had to create about 50 SOAP to REST APIs in a relatively short period of time, I came up with a scheme that used a specially-crafted XSLT file for each response and a single JSON cleanup function that could fix the array and data types coming out of the XMLToJSON policy. This was great for developer productivity (once I fought through the steep learning curve for XSLT). You can see an example of this solution at https://github.com/apigeecs/soap-xsl-example .

While the XSL policies performed well enough, it made sense to explore a JavaScript solution that doesn't require lots of custom code. I've created a JavaScript library, called JSMapr, that allows you to specify simple transformation steps to modify a JavaScript object in place. This can be used after an XMLToJSON policy to do complex conversions required for SOAP to REST proxies. A proxy using JSMapr to call the same SOAP backend as the XSL example can be found at https://github.com/apigeecs/soap-js-mapr .

thub.nodes.view.add-new-comment
jsonxmlsoap to restxmltojsonjsontoxml
Add comment Show 6
10 |5000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by Apigeeks only
  • Viewable by the original poster
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Varun Singh   · Jun 17, 2016 at 07:27 AM 0
Link

I am facing one issue with the XML to JSON conversion policy. I am getting XML response from backend. XML contains certain element which can appear once or multiple times. After getting the response from BE, I am using XMLtoJSON policy to convert it to JSON format.

Input :

<tac>adadadada</tac> <tac>asasasasa</tac> <id>12121212112</id> <version>1.0</version>

Output :

{"tac" : [adadadada, asasasasa], "id" : 12121212112, "version" : "1.0"}

Now if tac element is appearing only once then input and output is as follows.

Input :

<tac>asasasasa</tac> <id>12121212112</id> <version>1.0</version>

Output :

{"tac" : asasasasa, "id" : 12121212112, "version" : "1.0"}

As it clear from mentioned two payload that tac element could be a single value or Array. So, In our API flow, we have to check if tac is an instance of Array or not.

Then depending on the condition, We are proceeding ahead with the northbound response.

Does XML to JSON policy provides capabilities which allows API developer to configure within the policy itself if they want certain element to converted to be an array even though element is appearing only once in XML payload.

So if, API developer is configuring tac element for array then response could be like this from XMLtoJSON policy itself.

{"tac" : [asasasasa], "id" : 12121212112, "version" : "1.0"}

In this case, no need to check the instance of object for Array going forward.

Also, If this feature not available then can we have this kind of feature in recent times.

Thanks,

Varun

avatar image Eric Hildum Varun Singh · Jul 12, 2016 at 12:06 AM 0
Link

Edge's XMLtoJSON policy is probably the wrong choice for anything but trivial XML responses. Assuming you have a properly defined XML document with an associated XSD schema, you should use a message validation policy to validate the XML, then apply and XSLT to transform the XML to valid JSON directly with an XSL transformation policy. You can then control the way the XML is transformed to JSON (e.g., building arrays consistently when you need them) - remember, XML has far more accurate data type specification capability than JSON, which has only four data types (string, boolean, floating point, object {arrays are objects}). The following project may help you get started on your XSLT: https://github.com/bramstein/xsltjson.

Unfortunately, the JSON to XML path is a bit harder - that policy does not have the option to allow an XSD to guide the transformation to XML. Nor does JSON have the equivalent of schemas to ensure that your data is well formed. You will have to trust that your JSON source is correctly formatted by the source, and prepare for the possibility that the resulting XML data will be rejected as malformed by the destination.

avatar image Mike Dunker @Google ♦♦ Eric Hildum   · Jul 15, 2016 at 05:58 PM 0
Link

Agreed -- XML when used with an XSD schema does have rich typing.

avatar image Dino ♦♦ Varun Singh   · Mar 06, 2018 at 07:54 PM 0
Link

Yes, since some time in 2016, the XMLToJSON policy includes a TreatAsArray element to solve the problem you are describing.

avatar image Eric Hildum · Jul 12, 2016 at 12:58 AM 0
Link

Why the statement "XML is allowed to span multiple lines. JSON cannot be multi-line.

As developers, we get used to seeing nicely-formatted JSON spanning multiple lines. This is pretty-printed JSON. It is not valid JSON."

ECMA 404, The JSON Data Interchange Format specifically states: Insignificant whitespace is allowed before or after any token. The whitespace characters are: character tabulation (U+0009), line feed (U+000A), carriage return (U+000D), and space (U+0020). Whitespace is not allowed within any token, except that space is allowed in strings.

avatar image Mike Dunker @Google ♦♦ Eric Hildum   · Jul 15, 2016 at 05:57 PM 0
Link

You are correct -- ECMA 404 (Oct 2013) allows for JSON to span multiple lines, though earlier JSON specs did not allow this. Legacy parsers may possibly have issues, but I'll change wording.

Article

Contributors

avatar image avatar image

Follow this article

9 People are following this .

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Navigation

Converting between XML and JSON with Apigee Edge: what you need to know

Related Articles

Tutorial: XMLToJSON and JSONToXML policies in Apigee Edge

Tutorial : Convert your web service from SOAP to REST API using Apigee Edge in few minutes

How to trace a SOAP message on Apigee

REST-SOAP with MTOM Support

How to integrate web service between IBM Datapower and Apigee Edge in few minutes

How do I "easily" insert variables into JSON Payloads?

Tutorial: Service Virtualization - Dynamic Field Filtering of JSON responses

How can you Extract all values from a JSON hash into context variables?

Tutorial: the TreatAsArray option in the XMLToJSON policy

  • Products
    • Edge - APIs
    • Insights - Big Data
    • Plans
  • Developers
    • Overview
    • Documentation
  • Resources
    • Overview
    • Blog
    • Apigee Institute
    • Academy
    • Documentation
  • Company
    • Overview
    • Press
    • Customers
    • Partners
    • Team
    • Events
    • Careers
    • Contact Us
  • Support
    • Support Overview
    • Documentation
    • Status
    • Edge Support Portal
    • Privacy Policy
    • Terms & Conditions
© 2021 Apigee Corp. All rights reserved. - Apigee Community Terms of Use - Powered by AnswerHub
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Create an article
  • Post an idea
  • Spaces
  • Product Announcements
  • General
  • Edge/API Management
  • Developer Portal (Drupal-based)
  • Developer Portal (Integrated)
  • API Design
  • APIM on Istio
  • Extensions
  • Business of APIs
  • Academy/Certification
  • Adapter for Envoy
  • Analytics
  • Events
  • Hybrid
  • Integration (AWS, PCF, Etc.)
  • Microgateway
  • Monetization
  • Private Cloud Deployment
  • 日本語コミュニティ
  • Insights
  • IoT Apigee Link
  • BaaS/Usergrid
  • BaaS Transition/Migration
  • Apigee-127
  • New Customers
  • Explore
  • Topics
  • Questions
  • Articles
  • Ideas
  • Badges