Passing JSON Arrays to VM files asynchorously

I am working on a widget which pulls search result data in a JSM file it repruposes the data before rendering in the VM file on page load. When we want to dynamically refresh these results we use the same JSM file and result object but call the exetuced flie via ajax with POST. In the main this works with simple properties being set via the body, string intergers etc.. but as search sends an array of objects, when I pass these through core_v2_utility..ParseJson returns null.

After a fair bit of searching and testing it seems that the ParseJson function only works on JSON objects and breaks when an array of objects is passed to it.

#set ($json = '[{ "foo": 1}, {"foo": 2 }]')
#set ($parsed = $core_v2_utility.ParseJson($json))
## item is Null

#if($parsed)
    Parsed: $parsed
#else
    >> Parsed JSON Array is Null
#end

#set ($json1 = '{ "foo": 1}')
#set ($parsed1 = $core_v2_utility.ParseJson($json1))
## item is Null

#if($parsed1)
    Parsed Object: $parsed1
#else
    >> Parsed JSON is Null
#end

This example only highlights that the array returns null. Interestingly in velocity, if you have a property which is an array it can handle that. But none of that helps when you are sending post data from and async js call.

Is there a pattern that I am missing which would make this much simpler?

Currently I am using Newtonsoft.Json.Deserialize to give me the array of objects but that means I have to access the objects like Object.Proprerty.Value whcih is not compatible with the velocity template and requires extra work. One workaroud I have found for this is to use `ParseJson(ToJson( $item ))` wihtin a foreach to get the data to be in the correct structure again.

Any advice appreciated.

  • Former Member
    0 Former Member

    You can wrap your array in an object property, and then access that property instead of the entire parsed object:

    #set ($json = '{"array": [{ "foo": 1}, {"foo": 2 }]}')
    #set ($parsed = $core_v2_utility.ParseJson($json))
    ## item is Null
    
    #if($parsed)
        Parsed: $parsed.array
    #else
        >> Parsed JSON Array is Null
    #end
     

  • I had a lightbulb moment after writing the post asking for help. I was thinking about how a JSON Deserializer would be almost useless if it could not handle a property which contained a JSON array. So I did a little test and it could handle it. Thanks for confirming.

    This means that if you want to post data you can just structure your post body so that it is provided with an initial JSON property. Then ParseJson can do it's thing unhindered. The problem is with the root data type being an array. For anyone else who hits this issue I have just put together a quick example to show the pattern.

    // Some Endpoint request to a .VM file
    var data = {
      result: [{foo: 1},{ foo: 2}],
      someProperty: 1
    }
    $.telligent.evolution.post({
      url: endpoint,
      data: {
        response: JSON.stringify(data)
      }
    })

    ## Velocity processing  posted data
    #set ($resposne = $core_v2_utility.ParseJson($core_v2_page.GetFormValue('response')))
    #set ($resultSet = $response.result)
    
    #foreach ($item in $resultSet)
      $item.foo
      ## outputs 1, 2
    #end