javajsonvelocityxwiki

Get JSON data from JAVA component to XWiki apache velocity


What is the best way to get JSON data from a java component in xwiki runnung apache. In my java component I'm compiling JSONObjects and JSONArrays, I would like to return this data to my velocity script in JSON format, is this possible?

something like:

{{velocity wiki="false"}}
    #if("$!request.outputSyntax" != '')
      $response.setContentType('application/json')
    #end
    #set($map = {})
    #set ($rightIN =  ${request.rightIN})
    #set ($spacenameIN =  ${request.spacenameIN})
#set($disgard =$map.add($services.getjsondata.javacomp($spacenameIN,$rightIN)))
    $jsontool.serialize($map)
 {{/velocity}}

and the Java:

      public JSONObject javacomp(String spacenameIN, String rightIN ){
              JSONObject obj = new JSONObject();
              try {
                    obj.put("spacenameIN ", spacenameIN );
                    obj.put("rightIN", rightIN );
            } catch (JSONException e) {
                    e.printStackTrace();
            }
              return obj;
      }

At the end I would like to access this json object as a data return from an ajax call. Is this possible?

I'm currently returning strings, but this is very inefficient how can I return objects?


Solution

  • In your code above, the Java component returns a JSONObject but then, in Velocity, you try to add that object directly to a map, not specifying any key.

    So your velocity code should be changed to:

    #set ($map = $services.getjsondata.javacomp($spacenameIN, $rightIN))
    

    ...since the JSONObject instance is pretty much a map.

    After that, it's perfectly fine to serialize that map to JSON with:

    $jsontool.serialize($map)
    

    At the end I would like to access this json object as a data return from an ajax call. Is this possible?

    Sure, just remember to also set the content type of your result in Velocity, so that your ajax call properly interprets the Velocity result as JSON, and not as regular text. To do that you need to do:

    #set ($discard = $response.setContentType('application/json'))
    

    I'm currently returning strings, but this is very inefficient how can I return objects?

    Your Java component (script service) always returns objects to the Velocity side (they both execute on the server). It' your choice if those objects are strings or any other data type. You do not really need to handle the JSON serialization in the Java component (you just need to be careful that they are serializable types that $jsontool can handle when it will be called on the Velocity side). On the Velocity side, you do something with those objects and serialize them to JOSN (which is text/strings in the end because that's what the AJAX call needs since JavaScript is executed on the client side).

    Additionally, I would suggest you avoid JSONObject altogether and use a regular Map to pass your results to the Velocity side.