0

I have an array list multi map -

ArrayListMultimap<String, String> fcmbuildProperties = ArrayListMultimap.create();
ArrayListMultimap<String, String> scm = ArrayListMultimap.create();
//HashMap<String, String> fcmbuildProperties= new HashMap<String, String>();
fcmbuildProperties.put("name", buildName);
fcmbuildProperties.put("timestamp", buildTimeStamp);
fcmbuildProperties.put("groupId", groupID);
fcmbuildProperties.put("artifactId", artifactID);
fcmbuildProperties.put("version", version);
fcmbuildProperties.put("environment", environment);
fcmbuildProperties.put("number", patch);
fcmbuildProperties.put("artifactPath", layoutPath);
fcmbuildProperties.put("architecture", architecture);
fcmbuildProperties.put("operatingSystem", operatingSystem);
scm.put("commit",commitSha);
scm.put("url", githubUrl);
scm.put("branch", githubBranch);

This shows up as json like below :

{
  "operatingSystem": [
    "rhel5"
  ],
  "artifactPath": [
    "djin/platform/cache/test/rhel5/i386/packages/test/test-1.0.0-d.284.i386.rpm"
  ],
  "artifactId": [
    "test"
  ],
  "number": [
    "284"
  ],
  "architecture": [
    "i386"
  ],
  "url": [
    null
  ],
  "version": [
    "1.0.0"
  ],
  "timestamp": [
    "6/4/15/2015/11:22:7"
  ],
  "groupId": [
    "cache"
  ],
  "environment": [
    "snapshot"
  ],
  "commit": [
    null
  ],
  "name": [
    "fcm-dummy-web"
  ],
  "branch": [
    null
  ]
}

but how I need it to be parsed as:

{
    "name": "fcm-dummy-web",
    "url": "job/fcm-dummy-web/",
    "build": {
        "full_url": "job/fcm-dummy-web/29/",
        "number": 38,
        "url": "job/fcm-dummy-web/29/",
        "scm": {
            "url": "institutional/fcm-dummy-web",
            "branch": "origin/master",
            "commit": "989f0b78470f0dc9e262cc020e66837beef16c4e"
        },
        "artifacts": {
            "id": "test",
            "groupId": "djin/platform/cache",
            "operatingSystem": "rhel5",
            "environment": "snapshot",
            "path": "/cache/test/rhel5/i386/packages/testtest-1.0.0-d.269.i386.msi",
            "architecture": "i386",
            "version": "1.0.0"
        }
    }
}

So more nested json than a flat structure. What is an efficient way to proceed for this?

I use gson to make son from the arrayListMultimap:

Gson gson = new Gson();
String jsonString = gson.toJson(fcmbuildProperties.asMap()); 
ivant
  • 3,909
  • 1
  • 25
  • 39
Scooby
  • 3,371
  • 8
  • 44
  • 84
  • What is `ArrayListMultiMap`? – Chetan Kinger May 15 '15 at 15:40
  • do you want it automatically done or will you create the JSON by adding them one by one ? –  May 15 '15 at 15:43
  • ChetanKinger - Im sure you can google that. @DAO - automatically would be fantastic or I could do it one by one. – Scooby May 15 '15 at 15:58
  • @Scooby, `ArrayListMultiMap` is not a standard class. Please specify where we can see it. Also, your code creates `scm` and puts some elements in it, but it's never attached to `fcmbuildProperties`. – ivant May 16 '15 at 05:33

2 Answers2

2

It depends which library you're using for the JSON serialization.

Many libraries offer "pretty printing" which is a common attribute:

Pretty printing JSON from Jackson 2.2's ObjectMapper

Pretty-Print JSON in Java

Edit: With Gson it's simple

Gson gson = new GsonBuilder().setPrettyPrinting().create();

when creating the Gson object.

Edit 2:

public static class OuterObject {
    String name;
    String url;

    BuildProperties properties;

}

public static class BuildProperties {
    String full_url;
    int number;
    Map<String, String> scm = new HashMap<String, String>() {{
        put("url":"institutional/fcm-dummy-web");
        //etc
    }};

}
Community
  • 1
  • 1
Thomas Nairn
  • 1,186
  • 8
  • 34
  • I use gson, anyways to do it via gson ? – Scooby May 15 '15 at 15:54
  • I think you got confused with what I want, I don't want pretty printing. I want a nested JSON instead of a flat one in my example. So for example : I have flat key value pairs and I want a couple of them nested under "Build" . I want to know an easy way of doing that. – Scooby May 15 '15 at 16:06
  • Ah apologies, rather than use the giant list of properties, why not create a POJO around it? I'll update my answer – Thomas Nairn May 15 '15 at 16:07
  • Isn't this just a flat key,value pair ? where do I introduce nesting ? – Scooby May 15 '15 at 16:23
  • @Scooby, your question was quite ambiguous. I too thought that you wan't pretty-printing, mainly because the first json was in one-line and the second one -- pretty printed. I had to reformat it to see that they have different structures. Please, put some more work in asking a question and don't be too quick to vote down answers. – ivant May 16 '15 at 05:38
  • @Scooby The nesting is there with the nested objects OuterObject has a nested BuildProperties object. It'll show up nested in the JSON – Thomas Nairn May 16 '15 at 09:35
  • @ivant - I did not vote your answer down or for that matter any answer down. Someone else did not agree with your answer/which ever answer you are referring to and voted it down. I don't think my question was ambiguous, sure the format of the first son might have been not easily spotted. – Scooby May 16 '15 at 15:59
  • I apologize, then. I didn't know who voted it down and assumed it was you. P.S. it wasn't my answer. – ivant May 16 '15 at 16:41
0

I'm assuming that ArrayListMultiMap is from Google Guava library.

If so, your code doesn't construct a deeply structured object, so GSON won't show deeper structure either.

One way to do that is to use normal maps like this:

Map<String, Object> scm = new LinkedListMap<>();
scm.put("url", "institutional/fcm-dummy-web");
// TODO put the rest of the properties

Map<String, Object> artifacts = new LinkedListMap<>();
// TODO put the corresponding properties

Map<String, Object> build = new LinkedListMap<>();
// TODO put the props
build.put("scm", scm);
build.put("artifacts", artifacts);

Map<String, Object> root = new LinkedListMap<>();
root.put("name", "fcm-dummy-web");
root.put("url", "job/fcm-dummy-web/");
root.put("build", build);

Now you can use GSON to print this map:

new GSON().toJson(root);

There are a couple things to note here: 1. We're using LinkedListMap so that elements are shown in the same order as we put them. You can use TreeMap to have them sorted instead by name instead. Using a normal HashMap will also work, but you may get different order each time you run this code. 2. The keys in the maps are Strings, but some of the values are Strings and others -- maps. So we have to use Map and thus loosing type checks.

Many times a better approach would be to create POJO classes for the objects. Here is one way to do it:

public class BuildProperties {
    private String name;
    private Sting uri;
    private Build build;

    // TODO write getters and setters
}

public class Build {
    private String full_url;
    // ....
    private Scm scm;
    private Artifacts artifacts;

    // TODO write getters and setters
}

// TODO write the Scm and Artifacts classes

One thing that bothers me is the Artifacts part. Your JSON has a place for just one artifact there. What you probably need is for it to look like this:

"artifacts": [
    {
        "id": "test",
        "groupId": "djin/platform/cache",
        "operatingSystem": "rhel5",
        "environment": "snapshot",
        "path": "/cache/test/rhel5/i386/packages/testtest-1.0.0-d.269.i386.msi",
        "architecture": "i386",
        "version": "1.0.0"
    }
]

To get this with the maps code you have to change it like this:

Map<String, Object> artifact1 = new LinkedListMap();
artifact1.put("id", "test");
// ...
List<Map<String, Object>> artifacts = new ArrayList<>();
artifacts.add(artifact1);

And with the POJO code the Build class should look like this:

public class Build {
    private String full_url;
    // ....
    private Scm scm;
    private List<Artifact> artifacts;

    // TODO write getters and setters
}

And the class should be Artifact for a single artifact.

ivant
  • 3,909
  • 1
  • 25
  • 39