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

Former Community Member
Not applicable
7 8 63K

Often you get into a situation where within an API Proxy you may need to insert some variable data into a JSON payload that is needed by your back-end or target service. You can leverage the AssignMessage policy to do that. For eg:

<AssignMessage name="AssignMessage">
    <Set>
      <Payload contentType="application/json">
      	{"name":"foo", "type":"bar"}
      </Payload>
    </Set>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
    <AssignTo createNew="false" transport="http" type="request"/>
</AssignMessage>

The above is ok so long as you are not using any variables to populate the JSON payload. But there's no fun in sending static payloads! how do I then insert variable data in the payload?

It's very easy, like this:

<AssignMessage name="AssignMessage">
    <Set>
      <Headers/>
      <Payload contentType="application/json">
{
  "prop1":"foo", 
  "prop2":"{variable_name}",
  "prop3":"{system.timestamp}"
}
</Payload>
    </Set>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
    <AssignTo createNew="false" transport="http" type="request"/>
</AssignMessage>

Each of the strings surrounded by {curly braces} is interpreted as a variable name. The rule is: if there is an open curly and a close curly, and all the characters between are legal characters for a variable name (alphanumerics plus dot and underscore), then the sequence is treated as a variable reference.

So, something like this:

{variable_name}

...is treated as a variable name, when it appears inside the Payload element.

Something like this:

{ "prop1 : "foo" }

...is not treated as a variable reference. Notice there are spaces, quotes, and a colon between those curlies. Even if the variable reference appears between double quotes, like this:

"{variable_name}"

...the variable will be de-referenced. You can also combine multiple variables in a single line, like this:

{ "prop1 : "foo-{variable1}-{variable2}" }

If the referenced variable name can be resolved, then at runtime, the reference is replaced with the value of the variable. If variable name cannot be resolved then... based on the "true" value of the IgnoreUnresolvedVariables element, then the unknown variable name is replaced with a blank string. On the other hand if IgnoreUnresolvedVariables is false, the policy will throw the proxy into Fault status if there are unresolved variable references.

You can use built-in variables like system.timestamp, or custom variables that the proxy has filled via other policies, like ExtractVariables, KVM-Get or PopulateCache. The same approach works for populating XML payloads, of course.

Creating dynamic JSON messages used to be trickier. Previously the logic that handled the message template was somewhat naive; it interpreted any open curly brace as being the start of a variable reference. To get around that, the AssignMessage policy allowe the "variablePrefix" and "variableSuffix" properties. You might see some older examples employing this. They might look like this:

<AssignMessage name="AssignMessage">
    <Set>
      <Headers/>
      <Payload contentType="application/json" variablePrefix="@" variableSuffix="#">
      	{"prop1":"foo", "prop2":"@variable_name#"}
      </Payload>
    </Set>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
    <AssignTo createNew="false" transport="http" type="request"/>
</AssignMessage>

This works the same as the example above that used curlies. It still works today, but we have made AssignMessage smarter so that you no longer have to set the variablePrefix and variableSuffix. Just use curlies, and keep no spaces between the curlies and the variable names, and you should be good.

That's it. I hope this short writeup was helpful. Go JSON!

Comments
Not applicable

As Prithpal notes inserting JSON with an AssignMessage policy is quite doable.

In situations where you need to do just a bit more, we often see customers dropping into a Javascript callout to mediate the response. The following snippet gives you an idea of how we add/rename and delete payload elements within a Javascript callout:

context.setVariable("response.content", process(context.getVariable("response.content")));


function process(body) {
    obj = JSON.parse(body);
    if (obj.products)
        obj.products.forEach(function(product) {
            product.id = encodeURIComponent(product.id);
            product.sku= product.skuId;
            delete product.skuId;
        });


    return JSON.stringify(obj);
}

This example iterates over an array of products in the JSON payload, encoding each ID, copying a field to a new key, then deleting the legacy key value.

When AssignMessage is not enough, Javascript is your friend.

sgilson
New Member

Hi Prithpal,

Do you always have to precede JSON payloads with "\"?

Stephen

sgilson
New Member

You do not. In older versions of Apigee Edge, it was necessary. As of 2017, you do not need to use a leading "\" to escape the leading "{" in the JSON payload.

Not applicable

For me, variablePrefix="$" variableSuffix="%" seem to break use of the escape before the first curly brace - e.g.

<Payload contentType="application/json; charset=utf-8" variablePrefix="$" variableSuffix="%">
\{
  "fault": {
    "faultstring": "Request Failed",
    "detail": {
      "message": "Parameters were valid but request failed."
    }
  },
  "apiReturn": $someJSON.content%
}
</Payload>

...results in a payload full of escape chars - very ugly.

However, removing the variablePrefix="$" variableSuffix="%" makes it work fine.

Additionally, adding any variables still seems to work by just inserting the variable name within double quotes as the value for any property in the json - e.g.:

<Payload contentType="application/json; charset=utf-8">
\{
  "fault": {
    "faultstring": "Request Failed",
    "detail": {
      "message": "Parameters were valid but request failed."
    }
  },
  "apiReturn": "{someJSON.content}"
}
</Payload>

Results in the payload being returned, without any escape chars and with the variable value inside the curly brackets...

This seems different to the way it should work as described above...

Former Community Member
Not applicable

Hi @joshua.r.butler if you are using the variable prefix of "$" & variable suffix of "#" you shouldn't need to escape your first "{" like {\". If you do not specify the variable prefix & suffix the interpreter starts interpreting the first "{" it encounters as a variable.

Not applicable

@Prithpal Bhogill - thanks. It took me a bit of playing around to get it working - but yes, you're right. This is now working for me:

<Payload contentType="application/json" variablePrefix="$" variableSuffix="%">
    {
      "fault": {
        "faultstring": "$walletAdjustment.ReturnString%",
        "detail": {
          "message": "Parameters were valid but request failed."
        }
      },
      "apiReturn": "$purchaseJSON.content%"
    }
</payload>

MOST IMPORTANT THING TO NOTE:

Make sure to include the variables inside double quotes in cases where that variable might return json - otherwise it comes out with all the horrible escape chars. Took me a while to work that out.

sjm2000
Silver 1
Silver 1

Is it possible to do the same with SOAP?

DChiesa
Staff

yes, you can dynamically populate SOAP messages. It looks like this:

<AssignMessage name="AssignMessage-Title">
    <AssignTo createNew="false" transport="http" type="request"/>
    <Set>
        <Verb>POST</Verb>
        <Payload contentType="text/xml">
            <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
                <s:Header/>
                <s:Body>
                    <urn:findEntriesByTitle xmlns:urn="urn:librarysample.services.apigee.com">
                        <urn:title>{urielement.title}</urn:title>
                    </urn:findEntriesByTitle>
                </s:Body>
            </s:Envelope>
        </Payload>
    </Set>
    <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
</AssignMessage>

You can see a screencase on this, here.

Version history
Last update:
‎04-03-2015 02:39 PM
Updated by:
Former Community Member