Extract JSON from body into multiple variables

My API needs to perform an authorisation flow decision based on comparing the value of a claim presented incoming JWT and an incoming query param. The above all works fine if I put in a conditional 'raise fault' with following condition:

(message.queryparam.name_of_query != jwt.jwt.claim.name_of_jwt_claim)

However, the backend server doesn't accept queries using server?queryparam1=value&queryparam2=value, etc

Instead, it uses multiple JSON key value pairs into a single query param like so:

server X POST -d '{"field1":"xyz","field2":"123"}'

How do I parse the incoming request params into multiple flow variables so that I can make conditional access decisions based on one of the JSON key value pairs?

example: ($field1.variable != jwt.jwt.claim.name_of_jwt_claim)

Solved Solved
1 7 2,060
1 ACCEPTED SOLUTION

regarding this

server X POST -d '{"field1":"xyz","field2":"123"}'

What exactly does that imply? It looks something like the syntax for invoking a curl command from a bash shell. If that's what you're implying, then the argument to -d , the stuff in single quotes, is not a query param. It's the HTTP payload.

If you want to extract one (or a few) values from a JSON hash into context variables, you can use ExtractVariables policy to do that.

<ExtractVariables name='EV-1'>
  <Source>message</Source>
  <VariablePrefix>extracted</VariablePrefix>
  <JSONPayload>
    <Variable name='field1'>
       <JSONPath>$.field1</JSONPath>
    </Variable>
  </JSONPayload>
</ExtractVariables>

The result of that policy, given your example payload, would be that the variable named extracted.field1 will hold value "xyz".

You can also use AssignMessage to extract the value to a new variable.

<AssignMessage name='AM-ExtractField1'>
  <AssignVariable>
    <Name>extracted_field1</Name>
    <Template>{jsonPath($.field1,message.content)}</Template>
  </AssignVariable>
</AssignMessage>

The result of that is, the variable "extracted_field1" contains the value "xyz".

If you want to extract ALL values from the inbound JSON hash into "context variables", you cannot do that today, with an ExtractVariables policy or an AssignMessage policy.

To do that, please see this article.

View solution in original post

7 REPLIES 7

@Ivan Niccolai

You can extract each query parameter using extract variables - request.queryparam.paramname

Or you could use a javascript policy to extract the values and also build the json structure you need

thank you! do you know what flow variable to reference for the Extract variable policy, since this isn't a query parameter, but it is instead the data payload itself of the curl request?

The request payload will be in request.content variable. You can use jsonpath to extract the valuea. Make sure the content-type header has the right value.

regarding this

server X POST -d '{"field1":"xyz","field2":"123"}'

What exactly does that imply? It looks something like the syntax for invoking a curl command from a bash shell. If that's what you're implying, then the argument to -d , the stuff in single quotes, is not a query param. It's the HTTP payload.

If you want to extract one (or a few) values from a JSON hash into context variables, you can use ExtractVariables policy to do that.

<ExtractVariables name='EV-1'>
  <Source>message</Source>
  <VariablePrefix>extracted</VariablePrefix>
  <JSONPayload>
    <Variable name='field1'>
       <JSONPath>$.field1</JSONPath>
    </Variable>
  </JSONPayload>
</ExtractVariables>

The result of that policy, given your example payload, would be that the variable named extracted.field1 will hold value "xyz".

You can also use AssignMessage to extract the value to a new variable.

<AssignMessage name='AM-ExtractField1'>
  <AssignVariable>
    <Name>extracted_field1</Name>
    <Template>{jsonPath($.field1,message.content)}</Template>
  </AssignVariable>
</AssignMessage>

The result of that is, the variable "extracted_field1" contains the value "xyz".

If you want to extract ALL values from the inbound JSON hash into "context variables", you cannot do that today, with an ExtractVariables policy or an AssignMessage policy.

To do that, please see this article.

Yep, exactly. I resolved this with this Extract Variable policy:

<ExtractVariables name='...'>
  ...
  <Source>request</Source>
  <JSONPayload>
    <Variable name="field1" type="integer">
    <JSONPath>$.field1</JSONPath>
  </JSONPayload>
  ...
</ExtractVariables>

The above works for a POST verb with no query params. Now the next challenge is creating another policy for a request that arrives via GET. The JSON is passed in the same JSON format BUT as a queryparam :

'q={"field":"value"}'

I had this extract variable policy in the pre-flow and it would correctly evaluate and 403 error if a condition was not met, now putting this in a flow policy, only if the verb is POST, it just ignores the condition.

ExtractVariables works on a MESSAGE object. <Source>request</Source> is how you configure the specific message to use . And implicitly, when applying a JSONPath, it is evaluated against the PAYLOAD of the specified message. (Implicitly it uses request.content) . Which means extracting with ExtractVariables and JSONPath works for POST and PUT or other verbs that carry payloads. Since a GET request has no payload, ExtractVariables with JSONPath won't do anything interesting.

Your JSON is not contained in the request body. Therefore you cannot use ExtractVariables. Not directly anyway.

You have two options.

  • create a new contrived message object, just to hold the content that is in the query param.
    <AssignMessage name='AM-Contrived'>
      <AssignTo createNew='true' transport='http' type='request'>contrivedMessage</AssignTo>
      <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
      <Set>
        <Payload contentType='application/json'>{request.queryparam.q}</Payload>
        <Verb>POST</Verb>
      </Set>
    </AssignMessage>
    

    Then use ExtractVariables as above, but specify <Source>contrivedMessage</Source>

  • use AssignMessage/AssignVariable, with the jsonPath function, and specify request.queryparam.q as the source in the jsonPath function, rather than message.content.

    <AssignMessage name='AM-ExtractField1'>
      <AssignVariable>
        <Name>extracted_field1</Name>
        <Template>{jsonPath('$.field1',request.queryparam.q)}</Template>
      </AssignVariable>
    </AssignMessage>
    	

That first option worked. Thank you so much Dino!