How to template a json in java programming

Viewed 11906

My Use case is I have a json file but I have to share only few of them to client. Ex: Consider the source json file as shown below.

{
    "name": "XYZ",
    "age": 24,
    "education": {
        "college": "ppppp",
        "study": "b.tech",
        "grade": 6.8
    },
    "friends": ["kkkk",
    "bbbbbbbbbbb",
    "jjjjjj"],
    "dob":"01-08-1990"
}

For client 1 I have to share below output

{
    "personalInfo": {
        "name": "XYZ",
        "age": 24,
        "friendsNames": ["kkkk","bbbbbbbbbbb","jjjjjj"]
    },
    "educationalInfo": {
        "college": "ppppp",
        "study": "b.tech",
        "grade": 6.8
    }
}

For client 2 I have to share below output

{
    "personalInformation": {
        "nameOfEmployee": "XYZ",
        "ageOfEmployee": 24
    },
    "educationalInformation": {
        "college": "ppppp",
        "study": "b.tech"
    }
}

And for other clients also the use case is same, I have to skip some keys and give different names to the keys. How to dynamically do this by some kind of configuration. I used jsonPath to achieve this but removing few keys from json object is difficult. Any suggestions can be appreciated.

6 Answers

Use a JSON Path library, like JayWay. With that, templates to transform your exapmle would be:

Client 1

{
    "personalInfo": {
        "name": "$.name",
        "age": "$.age",
        "friendsNames": "$.friends"
    },
    "educationalInfo": "$.education"
}

Client 2

{
    "personalInformation": {
        "nameOfEmployee": "$.name",
        "ageOfEmployee": "$.age"
    },
    "educationalInformation": {
        "college": "$.education.college",
        "study": "$.education.study"
    }
}

What you need to implement is the template traversal. It's about 20 lines of code; or 40 if you also need to transform list elements, like:

{
    "friends": [ "$.friends[?(@ =~ /.{5,}/)]", {
        "name": "@",
        "since": "$.dob"
    } ]
}

which would result into:

{
    "friends": [ {
        "name": "bbbbbbbbbbb",
        "since": "01-08-1990"
    }, {
        "name": "jjjjjj",
        "since": "01-08-1990"
    } ]
}

You can use Jackson to serialize and deserialize json. I suggest you to create seperate classes which represents your client data.

I show you an example of how you can deserialize your data and map it to your client json.

You can generate corresponding classes for client 2 with getting some help from http://www.jsonschema2pojo.org/ for mapping json to pojo.

Here is the code :

public class Main {
    public static void main(String[] args) throws ParseException, ParserConfigurationException, IOException, SAXException {

        ObjectMapper mapper = new ObjectMapper();

        Root root = mapper.readValue(new File("test.json"), Root.class);

        Client1 c1 = new Client1();
        PersonalInfo personalInfo1 = new PersonalInfo();
        personalInfo1.setAge(root.getAge());
        personalInfo1.setFriendsNames(root.getFriends());
        personalInfo1.setName(root.getName());

        EducationalInfo educationalInfo1 = new EducationalInfo();
        educationalInfo1.setCollege(root.getEducation().getCollege());
        educationalInfo1.setGrade(root.getEducation().getGrade());
        educationalInfo1.setStudy(root.getEducation().getStudy());

        c1.setPersonalInfo(personalInfo1);
        c1.setEducationalInfo(educationalInfo1);

        mapper.writeValue(new File("client1.json"), c1);
    }
}

Inside test.json file :

{
  "name": "XYZ",
  "age": 24,
  "education": {
    "college": "ppppp",
    "study": "b.tech",
    "grade": 6.8
  },
  "friends": [
    "kkkk",
    "bbbbbbbbbbb",
    "jjjjjj"
  ],
  "dob": "01-08-1990"
}

Inside client1.json file :

{
  "personalInfo": {
    "name": "XYZ",
    "age": 24,
    "friendsNames": [
      "kkkk",
      "bbbbbbbbbbb",
      "jjjjjj"
    ]
  },
  "educationalInfo": {
    "college": "ppppp",
    "study": "b.tech",
    "grade": 6.8
  }
}

Here is the classes which represents your json data:

class Education {
    private String college;
    private String study;
    private float grade;

    public String getCollege() {
        return college;
    }

    public void setCollege(String college) {
        this.college = college;
    }

    public String getStudy() {
        return study;
    }

    public void setStudy(String study) {
        this.study = study;
    }

    public float getGrade() {
        return grade;
    }

    public void setGrade(float grade) {
        this.grade = grade;
    }
}

// root of your base json data
class Root {

    private String name;
    private int age;
    private Education education;
    private List<String> friends;
    private String dob;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Education getEducation() {
        return education;
    }

    public void setEducation(Education education) {
        this.education = education;
    }

    public List<String> getFriends() {
        return friends;
    }

    public void setFriends(List<String> friends) {
        this.friends = friends;
    }

    public String getDob() {
        return dob;
    }

    public void setDob(String dob) {
        this.dob = dob;
    }
}

class EducationalInfo {

    private String college;
    private String study;
    private float grade;

    public String getCollege() {
        return college;
    }

    public void setCollege(String college) {
        this.college = college;
    }

    public String getStudy() {
        return study;
    }

    public void setStudy(String study) {
        this.study = study;
    }

    public float getGrade() {
        return grade;
    }

    public void setGrade(float grade) {
        this.grade = grade;
    }
}

// class which represents client 1 json data
class Client1 {

    private PersonalInfo personalInfo;
    private EducationalInfo educationalInfo;

    public PersonalInfo getPersonalInfo() {
        return personalInfo;
    }

    public void setPersonalInfo(PersonalInfo personalInfo) {
        this.personalInfo = personalInfo;
    }

    public EducationalInfo getEducationalInfo() {
        return educationalInfo;
    }

    public void setEducationalInfo(EducationalInfo educationalInfo) {
        this.educationalInfo = educationalInfo;
    }
}

class PersonalInfo {

    private String name;
    private int age;
    private List<String> friendsNames = null;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public List<String> getFriendsNames() {
        return friendsNames;
    }

    public void setFriendsNames(List<String> friendsNames) {
        this.friendsNames = friendsNames;
    }
}

What about converting it to XML then create some XSLT? it might be much readable and cleaner.

I push full worked example in java into GIT with libs (lombok and jackson) Template json mapped to object and object to json with different clients.

Your job is to output multilevel JSON data as multiple JSON formats. JSONPath can do this but the process is a hassle.

A simple alternative is to use SPL. SPL is a Java open-source package. You just need three lines of code to get the job done:

enter image description here

SPL offers JDBC driver to be invoked by Java. Just store the above SPL script as jsonparse.splx and invoke it in a Java application as you call a stored procedure:

…
Class.forName("com.esproc.jdbc.InternalDriver");
con= DriverManager.getConnection("jdbc:esproc:local://");
st = con.prepareCall("call jsonparse()");
st.execute();
…

Java doesn't have great templating built in.

But if you want to do a quick an dirty JSON template where you can replace a few values -- especially without all that ugly quote escaping:

{"key":"value"}

You can use single quotes and string replace:

{'key':'VALUE'}.replace("'", """).replace("VALUE", 42)

A few caveats:

This will break if any existing keys or values have single quotes (like O'malley).

It won't replace strings with numbers, boolean, or null

It can't -- by itself -- insert nested arrays or objects (e.g. [] {}) other than as strings.

But with a little bit of of extra work, you can accomplish the 80/20 rule. After that point you'd probably want to look into parsing or generating -- but by then you're not looking for a quick template.

Related