Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simple template library with binding capability for Java

I want to generate valid JSON with the help of a template engine. In particular, I want the engine to replace the placeholders in the template with the properties of a model class. The engine should allow the use converters for complex classes like java.util.Date. Additionally, I do not want to explicitly handle lists in the template itself, instead I want any collection-like type to produce valid JSON arrays.

This could be an example of a template:

{
  "uber" :
  {
    "version" : "1.0",
    "data" :
    [
      {
        "rel" : $relations,
        "data" :
        [
          {"name" : "firstname", "value" : $firstname},
          {"name" : "lastname", "value" : $lastname}
        ]
      }
    ]
  }
}

I want to replace the variables ($relations, $firstname, $lastname) in this template from a model that has a relations, a firstname and a lastname property. This should also work for nested properties. (for example: $address.street)

After binding the model, the JSON could look like this:

{
  "uber" :
  {
    "version" : "1.0",
    "data" :
    [
      {
        "rel" : ["person"],
        "data" :
        [
          {"name" : "firstname", "label" : "Firstname", "value" : "Max"},
          {"name" : "lastname", "label" : "Lastname", "value" : "Mustermann"}
        ]
      }
    ]
  }
}

Please note, that the engine needs to take care of using quotation marks when necessary.

Is there any template library that is capable of doing this or do I need to roll my own library?

I have already looked into the following libraries:

  • Freemarker
  • Velocity
  • Stringtemplate

And I also read several threads:

  • Java Template library similar to ZPT (attribute language)
  • Spring template engine for rendering JSON

However, I did not find a satisfying solution up to now.

Background information:

Uber is domain-agnostic hypermedia format that nests data elements in order to encode the data. This format is very cumbersome to produce if you want to serialize it with a library like Jackson because you have to create a lot of objects and nested them via setters which results in a lot of code and is also very error-prone.

That is why I thought of using templates to generate the output and let the user write a template and later bind a model to this template to generate the output.

like image 416
Thomas Eizinger Avatar asked Nov 15 '15 13:11

Thomas Eizinger


1 Answers

I found an answer to my question:

I am using the following notation for variables in my template: $(json.path.to.value). I have implemented a custom Predicate from the JsonPath library by JayWay that looks for values in the JSON which conform to the variable definition.

The predicate also takes a DocumentContext which represents the model object, from which the values for the variables should be taken. This document context is created by serializing the model object with Jackson and re-reading it with the JsonPath library. This way, it is ensured that all tokens that are inserted in the template are valid JSON tokens.

If the predicate finds a variable, it extracts the containted JsonPath expression, looks for a new value in the provided DocumentContext and overrides the value in the original JSON.

like image 99
Thomas Eizinger Avatar answered Sep 28 '22 00:09

Thomas Eizinger