4

I am implementing a REST API which send and receive data with json(I am totally new to this API design). I am using Spring framework and requestbody/responsebody for mapping. Initially, I had a pojo like this:

public class Action implements Serializable {

    @Id
    private String id;
    private String name;
    private String applicationId;
    private String timeStamp;
    private String username;
    private String options;
    //Getters and Setters
}

and the json format for this pojo is like this:

{
 "id": "11954cd5-eec3-4f68-b0e8-a4d9b6a976a9",
 "name": "kill button",
 "applicationId": "34fa7bbf-e49f-4f2a-933a-de26b9fdb0f1",
 "timeStamp": "2014-03-05T11:51+0000",
 "username": "user1783",
 "options": "facebook app" 
}

This is how the controller look like:I do not get any json, Spring is converting already to java object, should it do it manually myself?

@RequestMapping(value = "applications/{appId}/actions", method = RequestMethod.POST, consumes = "application/json", produces = "application/json")
@ResponseBody
public Action addAction(@PathVariable String appId, @RequestBody Action action) {
    return actionService.add(appId, action);
}

you can find a pretty json format of it here: https://gist.github.com/bakharzy/8948950

I want to change the last pair in the json to be a json itself as it is shown in the second json format in gist. So user can send more information. Now that I have a new format for json which is kind of json in json, how should I change the pojo (private String options;) to store the data coming from second json format. Note that the inner json can have arbitrary number of pairs.

My first idea is to change the options in pojo to something like Hash object. Is it doable? If so, how?

Thanks

6
  • 1
    You can have nested Pojos. Commented Mar 6, 2014 at 0:05
  • Could you please explain more? Commented Mar 6, 2014 at 0:09
  • You can create an Options class and make an instance field of it in your Action class. Commented Mar 6, 2014 at 0:09
  • Why not just create the obvious Maps and JSON-encode them? Commented Mar 6, 2014 at 0:19
  • @user3207391 Please mark an answer as the solution if it solves your problem. Commented Mar 6, 2014 at 21:11

2 Answers 2

8

Just use a nested Object like so:

public class Action implements Serializable {

    @Id
    private String id;
    private String name;
    private String applicationId;
    private String timeStamp;
    private String username;
    private Map<String, String> options;
    //Getters and Setters
}

This will give you this format:

{
    "id": "11954cd5-eec3-4f68-b0e8-a4d9b6a976a9",
    "name": "kill button",
    "applicationId": "34fa7bbf-e49f-4f2a-933a-de26b9fdb0f1",
    "timeStamp": "2014-03-05T11:51+0000",
    "username": "user1783",
    "options":{
          "data": "Click Here",
          "size": "36",
          "application":"facebook app"
     }
}

UPDATE: - Adding test to prove that the solution does indeed work.

public class ActionTest {

        @Test
        public void testObjectToJson() throws JsonProcessingException {

            Action action = new Action();
            action.setId("id");
            action.setUsername("username");
            action.setApplicationId("applicationId");
            action.setName("name");
            action.setTimeStamp("timestamp");
            Map<String, String> map = Maps.newHashMap();
            map.put("key", "value");
            map.put("key2", "value2");
            action.setOptions(map);

            ObjectMapper mapper = new ObjectMapper();

            String value = mapper.writeValueAsString(action);
            System.out.println(value);
        }

        @Test
        public void testJsonToObject() throws IOException {

            String json = "{\"id\":\"id\",\"name\":\"name\",\"applicationId\":\"applicationId\",\"timeStamp\":\"timestamp\",\"username\":\"username\",\"options\":{\"key\":\"value\", \"key2\":\"value2\"}}";

            ObjectMapper mapper = new ObjectMapper();

            Action value = mapper.readValue(json, Action.class);
            System.out.println(value);
        }
    }

    class Action {

        private String id;
        private String name;
        private String applicationId;
        private String timeStamp;
        private String username;
        private Map<String, String> options;

        public Action() {}

        @Override
        public String toString() {
            final StringBuffer sb = new StringBuffer("Action{");
            sb.append("id='").append(id).append('\'');
            sb.append(", name='").append(name).append('\'');
            sb.append(", applicationId='").append(applicationId).append('\'');
            sb.append(", timeStamp='").append(timeStamp).append('\'');
            sb.append(", username='").append(username).append('\'');
            sb.append(", options=").append(options);
            sb.append('}');
            return sb.toString();
        }

        public String getId() {
            return id;
        }

        public void setId(String id) {
            this.id = id;
        }

        public String getName() {
            return name;
        }

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

        public String getApplicationId() {
            return applicationId;
        }

        public void setApplicationId(String applicationId) {
            this.applicationId = applicationId;
        }

        public String getTimeStamp() {
            return timeStamp;
        }

        public void setTimeStamp(String timeStamp) {
            this.timeStamp = timeStamp;
        }

        public String getUsername() {
            return username;
        }

        public void setUsername(String username) {
            this.username = username;
        }

        public Map<String, String> getOptions() {
            return options;
        }

        public void setOptions(Map<String, String> options) {
            this.options = options;
        }
    }
Sign up to request clarification or add additional context in comments.

13 Comments

Thanks.I want to give the user the flexibility to add arbitrary number of pairs to options. In my example, there are just 3 pairs, data, size and application. But I want it in a way which user can send 1 or more number of pairs in this options. Can you modify your solution for that?
@user3207391 - For that options must be a Map (or something that simulates one).
Let me make sure I understand what you're asking. You want to be able to pass in any number of fields in Options with varying keys (field name)?
yes ninnemannk, that is right. I think as Hot Licks said and I guessed, it can be done with Map structure.
@user3207391 - A map would give you the functionality you're looking for as Hot Licks has said.
|
-1
Map<String, Object> innerMap = new WhateverMap<String, Object>();
innerMap.put("data", "click here");
innerMap.put("size", "36");
innerMap.put("application", "facebook app");

Map<String, Object> outerMap = new WhateverMap<String, Object>();
outerMap.put("name", "kill button");
outerMap.put("username", "user1783");
outerMap.put("options", innerMap);

String jsonString = jsonEncoder.encode(outerMap);

13 Comments

This is fine when you don't care about your pojo mapping.. But when you're using direct pojo mapping for REST calls and using these objects in your application logic - this is not the way to go.
@ninnemannk - I don't know about that. Seems to me that lots of folks here are stumbling over the "automatic" POJO mapping of JSON when simply writing the code is simpler and clearer. (And what does this have to do with REST?)
OP clearly stated that he was writing a REST api. Passing around maps is not good for doing logic or persisting data.
@ninnemannk - REST has nothing to do with how you construct the JSON.
I said nothing about the structure of the json. I simply stated that when doing application logic inside of his api it will be much easier with a structured object (OOP) than passing around a HashMap.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.