Skip to content

Slicing and Dicing JSON and Java with Boon or how to customize JSON stream without having 20 Java DTO objects

Richard Hightower edited this page May 7, 2014 · 2 revisions

If you have 75 annotations in a Java class and 25 more in the REST handler than you are doing it wrong.

Boon was invented after looking at what a SaaS company needed, and seeing what frameworks they were currently using. Boon was the reaction to an idea of let's have 50 DTO to match each use case or view.

I could not handle writing 50 DTO objects for simple things, and I was sick of there being more annotations in my code then code, and class loaders issues, and , and … so Boon.

Let's say you have a large JSON stream / file / REST POST / Websocket call that looks like this:

##Sample JSON of teams

{

    "teamInfo" : {
        "teamRoster": {
            "teamNames": ["duck", "chickens", "penguins"]
        }

    }


} 

Sometimes you want to create a team info (TeamInfo). Sometimes you want just the list or Set. Sometimes you want just the team roster. Different use cases use different parts of the stream, perhaps the JSON stream even gets put onto a bus and many end points grab it and use different parts of the stream.

Sample classes (not DTO but domain objects).

    public static class TeamRoster {
        Set<String> teamNames;

        @Override
        public String toString() {
            return "TeamRoster{" +
                    "teamNames=" + teamNames +
                    '}';
        }
    }

    public static class TeamInfo {

        TeamRoster teamRoster;

        @Override
        public String toString() {
            return "TeamInfo{" +
                    "teamRoster=" + teamRoster +
                    '}';
        }
    }

In this example we will read the JSON with Boon from the classpath or file system with jsonResource (full example below).

        /* Using Boon style (easy) 2 parser. */
        jsonObject = Boon.jsonResource(path);

Now if we just want the team info part of the JSON we do this:

        /* Using Boon path. */
        puts ("teamInfo", atIndex(jsonObject, "teamInfo"));

(puts is like System.out.println but better)

teamInfo {teamRoster={teamNames=[duck, chickens, penguins]}} 

atIndex returns the teamInfo map.

You use atIndex to get just the part you care about. We can get the teamInfo, the teamRoster or the teamNames and different use cases (or different listeners on the bus might care about different things) so they can pick and choose what they want and ignore the rest. This is JSON. It is meant to be flexible.

Grabbing just the teamInfo.teamRoster

        puts("Team Roster", atIndex(jsonObject, "teamInfo.teamRoster"));

Grabbing just the teamInfo.teamRoster and teamInfo.teamRoster.teamNames

        puts("Team Roster", atIndex(jsonObject, "teamInfo.teamRoster"));
        puts("Team Names", atIndex(jsonObject, "teamInfo.teamRoster.teamNames"));

output

Team Roster {teamNames=[duck, chickens, penguins]} 
Team Names [duck, chickens, penguins] 

How do we convert team names into a Set?

Easy.

        List<String> teamNames = (List<String>) atIndex(jsonObject, "teamInfo.teamRoster.teamNames");

        puts("Team Names", teamNames);

        Set<String> teamNameSet = set(teamNames);

        puts ("Converted to a set", teamNameSet);

output

Team Names [duck, chickens, penguins] 
Converted to a set [duck, chickens, penguins] 

How do we convert a specific path into the TeamInfo domain object without converting the entire JSON stream?

Getting just the TeamInfo from JSON

        TeamInfo teamInfo = fromMap((Map<String, Object>) atIndex(jsonObject, "teamInfo"), TeamInfo.class);
        puts(teamInfo);

How do we convert a specific path into the TeamRoster domain object without converting the entire JSON stream?

Getting just the TeamRoster from JSON

        TeamRoster teamRoster = fromMap((Map<String, Object>) atIndex(jsonObject, "teamInfo.teamRoster"), TeamRoster.class);

Full example

/*
 */

package com.examples;

import org.boon.Boon;
import org.boon.IO;
import org.boon.json.JsonFactory;
import org.boon.json.JsonParserAndMapper;
import org.boon.json.JsonParserFactory;
import org.boon.json.ObjectMapper;

import java.io.File;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static org.boon.Boon.atIndex;
import static org.boon.Boon.puts;
import static org.boon.Maps.fromMap;
import static org.boon.Sets.set;

/**
 * Created by Richard on 5/6/14.
 */
public class PartialDataTreeExample {


    public static class TeamRoster {
        Set<String> teamNames;

        @Override
        public String toString() {
            return "TeamRoster{" +
                    "teamNames=" + teamNames +
                    '}';
        }
    }

    public static class TeamInfo {

        TeamRoster teamRoster;

        @Override
        public String toString() {
            return "TeamInfo{" +
                    "teamRoster=" + teamRoster +
                    '}';
        }
    }

    public static void main (String... args) {
        File file = new File(".", "src/test/resources/teams.json");
        String path = file.getAbsolutePath().toString();
        puts ("PATH", path);
        puts ("CONTENTS of PATH", IO.read(path));

        /* Jackson style interface. */
        ObjectMapper mapper = JsonFactory.create();
        Object jsonObject = mapper.readValue(file, Object.class);
        puts ("JSON Object", jsonObject);


        /* Using Boon path. */
        puts ("teamInfo", atIndex(jsonObject, "teamInfo"));
        puts("Team Roster", atIndex(jsonObject, "teamInfo.teamRoster"));
        puts("Team Names", atIndex(jsonObject, "teamInfo.teamRoster.teamNames"));


        /* Using Boon style parser (fast). */
        JsonParserAndMapper boonMapper = new JsonParserFactory().create();
        jsonObject = boonMapper.parseFile(path);


        /* Using Boon path. */
        puts ("teamInfo", atIndex(jsonObject, "teamInfo"));
        puts("Team Roster", atIndex(jsonObject, "teamInfo.teamRoster"));
        puts("Team Names", atIndex(jsonObject, "teamInfo.teamRoster.teamNames"));



        /* Using Boon style (easy) 2 parser. */
        jsonObject = Boon.jsonResource(path);


        /* Using Boon path. */
        puts ("teamInfo", atIndex(jsonObject, "teamInfo"));
        puts("Team Roster", atIndex(jsonObject, "teamInfo.teamRoster"));
        puts("Team Names", atIndex(jsonObject, "teamInfo.teamRoster.teamNames"));

        //There is also a Groovy style and a GSON style.

        List<String> teamNames = (List<String>) atIndex(jsonObject, "teamInfo.teamRoster.teamNames");

        puts("Team Names", teamNames);

        Set<String> teamNameSet = set(teamNames);

        puts ("Converted to a set", teamNameSet);


        TeamInfo teamInfo = fromMap((Map<String, Object>) atIndex(jsonObject, "teamInfo"), TeamInfo.class);
        puts(teamInfo);


        TeamRoster teamRoster = fromMap((Map<String, Object>) atIndex(jsonObject, "teamInfo.teamRoster"), TeamRoster.class);
        puts(teamRoster);

    }

}
Clone this wiki locally