Announcement Announcement Module
Collapse
No announcement yet.
Examples to make RestTemplate work with JSON? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Examples to make RestTemplate work with JSON?

    The first time I saw http://static.springsource.org/sprin...plate-example2 I thougt This is the framework to go! Now after 3 days on it I feel kinda different about it. (You can check my last posts in this forum)

    If somebody got it RestTemplate working with JSON...
    • Could u please provide me the JSON file for example 3.4 from the link posted above or another json file with corresponding Template class?
    • How to deal with nested attributes in JSON?
    • How to use @Ignore-Annotations?
    • I also tried to use a wrapper class like the "IssueResponse" here with no luck



    This example seems to come from the greenhouse app which crashes when hidding the "Sign in" button. So, no JSON files can be examined there. Sorry, spring I am really going to feel different about your framework...
    Last edited by OneWorld123; Dec 15th, 2010, 08:48 AM.

  • #2
    Re: Examples to make RestTemplate work with JSON?

    How about we take one bullet point at a time.

    Using Jersey on the server-side, we have a simple REST-based call: http://localhost:9998/event/1

    It returns an event like this:

    {"id":"1","title":"Train Concert"}

    You can check what is coming across using a tool like TcpMon.

    On the Android side, the code looks like this:

    Code:
    RestTemplate restTemplate = new RestTemplate();
        	
    List<HttpMessageConverter<?>> messageConverters = new ArrayList<HttpMessageConverter<?>>();
    messageConverters.add(new FormHttpMessageConverter());
    messageConverters.add(new StringHttpMessageConverter());
    messageConverters.add(new MappingJacksonHttpMessageConverter());
    restTemplate.setMessageConverters(messageConverters);
    		
    restTemplate.setRequestFactory(new CommonsClientHttpRequestFactory());
    String url = "http://10.1.1.40:9998/event/1";
    Event event = restTemplate.getForObject(url, Event.class);
    Make sure the Event class within your Android call has an empty constructor, otherwise Jackson will complain that there is no simple constructor.

    Perry Hoekstra

    Comment


    • #3
      After a lot of trial and error I got it working. Take a look at my results...

      Example:

      Execution of the getForObjectMethod
      Code:
      RestTemplate restTemplate = new RestTemplate();
      restTemplate.setRequestFactory(new CommonsClientHttpRequestFactory());
      //fill the rest template
      MyObjectResponse objectResponse = restTemplate.getForObject("http://someurl", MyObjectResponse.class);
      The wrapper file
      Code:
      public class MyObjectResponse {
        
        private MyObject myObject;
      
        public MyObject getMyObject() {
          return myObject;
        }
      
        public void setMyObject( MyObject myObject ) {
          this.myObject = myObject;
        }
      }
      class "myObject"
      Code:
      import org.codehaus.jackson.annotate.JsonIgnoreProperties;
      import org.codehaus.jackson.annotate.JsonProperty;
      
      @JsonIgnoreProperties(ignoreUnknown = true) //must be there all times most likely
      public class MyObject {
        /*
         * Attributes
         */
      
        @JsonProperty //this annotation is also necessary
        private String title;
        @JsonProperty
        private String id, created_at, updated_at;
        @JsonProperty
        private Image[] images;
      
      /*
       * All Attributes have getters and setters (generated by Eclipse - right click - source - generate getters and setters)
       */
      The nested image class
      Code:
      import org.codehaus.jackson.annotate.JsonIgnoreProperties;
      import org.codehaus.jackson.annotate.JsonProperty;
      
      @JsonIgnoreProperties(ignoreUnknown = true)
      public class Image {
      
        @JsonProperty
        private Integer width, height;
        @JsonProperty
        private String url, type, size;
        
        public Integer getWidth() {
          return width;
        }
        public void setWidth( Integer width ) {
          this.width = width;
        }
        public Integer getHeight() {
          return height;
        }
        public void setHeight( Integer height ) {
          this.height = height;
        }
        public String getUrl() {
          return url;
        }
        public void setUrl( String url ) {
          this.url = url;
        }
        public String getType() {
          return type;
        }
        public void setType( String type ) {
          this.type = type;
        }
        public String getSize() {
          return size;
        }
        public void setSize( String size ) {
          this.size = size;
        }
      
      }

      Comment


      • #4
        Here is the JSON file:

        Code:
        {"myObject":{"title":"this is the title","created_at":"2010-08-26T15:21:30+02:00","images":[{"rel":"icon","url":"/someurl.png","type":"image/png","height":"16","width":"32"},{"rel":"preview","url":"/someurl.png","type":"image/png","height":"34","width":"68"}]}
        Make sure the Event class within your Android call has an empty constructor, otherwise Jackson will complain that there is no simple constructor.
        Ok, I will look into that. Maybe then I dont have to use the "wrapper"

        Comment


        • #5
          Re: How to deal with nested attributes in JSON?

          Talking to your second bullet point, let's augment Event with a collection like this:

          Code:
          public class Event {
              private Long id;
          
              private String title;
          	
          
              private ArrayList<Location> locations = new ArrayList<Location>();
              
              public Event() {	
              }
              
              public Event(Long id, String title) {
              	this.id = id;
              	this.title = title;
              }
              
              public Long getId() {
                  return id;
              }
          
              public void setId(Long id) {
                  this.id = id;
              }
          
              public String getTitle() {
                  return title;
              }
          	
              public void setTitle(String title) {
                  this.title = title;
              }
          
              public ArrayList<Location> getLocations() {
          	return locations;
              }
              
              public void setLocations(ArrayList<Location> locations) {
                	this.locations = locations;
              }
          }
          The new JSON reply from the REST server looks like this (again, gotta love TcpMon):

          {"id":"1","Locations":{"city":"Boston","state":"MA "},"title":"Train Concert"}

          This time, we alter the restTemplate.getForObject to use String and use the JSON object that is part of Android:

          Code:
          String event = restTemplate.getForObject(url, String.class);
          		
          try {
          	JSONObject jsonObject = new JSONObject(event);
          		
          	Log.d(TAG, "Result: [" + jsonObject.get("id") + "]");
          	Log.d(TAG, "Result: [" + jsonObject.get("title") + "]");		
          	Log.d(TAG, "Result: [" + jsonObject.get("Locations") + "]");		
          } 
          catch (JSONException e) {
          	e.printStackTrace();
          }

          Comment


          • #6
            I added an empty contructor to "MyObject" and put "MyObject.class" into the getForObject method.

            Result: all attributes are null.

            So I remain using the wrappe and dont use empty constructors. Jackson doesnt complain about it

            Comment


            • #7
              @dutchman: I think u forgot the @Annotations in our Event class which are required for the JacksonJSONparser

              Comment


              • #8
                Re: Examples to make RestTemplate work with JSON?

                No, I am not using Jackson in this case, just the org.json.* classes embedded with Android. Therefore I don't need the @Annotation entries.

                Comment


                • #9
                  Originally posted by dutchman_mn View Post
                  No, I am not using Jackson in this case, just the org.json.* classes embedded with Android. Therefore I don't need the @Annotation entries.
                  How? Could you provide me the code? Thx!

                  Comment


                  • #10
                    Re: Examples to make RestTemplate work with JSON

                    Here are the Event and Location business objects:

                    Code:
                    public class Event {
                        private Long id;
                    
                        private String title;
                    	
                        private ArrayList<Location> locations = new ArrayList<Location>();
                        
                        public Event() {	
                        }
                        
                        public Event(Long id, String title) {
                        	this.id = id;
                        	this.title = title;
                        }
                        
                        public Long getId() {
                            return id;
                        }
                    
                        public void setId(Long id) {
                            this.id = id;
                        }
                    
                        public String getTitle() {
                            return title;
                        }
                    	
                        public void setTitle(String title) {
                            this.title = title;
                        }
                    
                        public ArrayList<Location> getLocations() {
                    		return locations;
                        }
                        
                        public void setLocations(ArrayList<Location> locations) {
                    	this.locations = locations;
                        }
                    }
                    
                    public class Location {
                    	private String city;
                    	private String state;
                    	
                        public Location() {    	
                        }
                        
                        public Location(String city, String state) {
                        	this.city = city;
                        	this.state = state;
                        }
                        
                        public String getCity() {
                            return city;
                        }
                    	
                        public void setCity(String city) {
                            this.city = city;
                        }    
                        
                        public String getState() {
                            return state;
                        }
                    	
                        public void setState(String state) {
                            this.state = state;
                        }        
                    }
                    and here is the code that parses the JSON response into Event and Location objects:

                    Code:
                        RestTemplate restTemplate = new RestTemplate();
                        	
                        List<HttpMessageConverter<?>> messageConverters = new ArrayList<HttpMessageConverter<?>>();
                        messageConverters.add(new FormHttpMessageConverter());
                        messageConverters.add(new StringHttpMessageConverter());
                        messageConverters.add(new MappingJacksonHttpMessageConverter());
                        restTemplate.setMessageConverters(messageConverters);
                    		
                        restTemplate.setRequestFactory(new CommonsClientHttpRequestFactory());
                        String url = "http://10.1.1.40:9998/event/1";
                        String event = restTemplate.getForObject(url, String.class);
                    		
                        try {
                    	JSONObject jsonObject = new JSONObject(event);
                    			
                    	Log.d(TAG, "Result: [" + jsonObject.get("id") + "]");
                    	Log.d(TAG, "Result: [" + jsonObject.get("title") + "]");		
                    	Log.d(TAG, "Result: [" + jsonObject.get("Locations") + "]");		
                        } 
                        catch (JSONException e) {
                    	e.printStackTrace();
                        }

                    Comment


                    • #11
                      I dont see you taking use of the Event and Location objects in the 2nd code frame.

                      You just download the resource and parse them to String with the help of RestTemplate. Later on u parse the String "event" into a JSON object afterwards which apparently doesnt correspond to your Event and Location objects.

                      You also dont need to
                      Code:
                      messageConverters.add(new MappingJacksonHttpMessageConverter());
                      since only use the StringMessageConverter.

                      Comment


                      • #12
                        Re: Examples to make RestTemplate work with JSON?

                        I don't know why you feel the need to deserialize the object but here you go:

                        Code:
                        GsonBuilder gsonb = new GsonBuilder();
                        Gson gson = gsonb.create();
                        
                        RestTemplate restTemplate = new RestTemplate();
                            	
                        List<HttpMessageConverter<?>> messageConverters = new ArrayList<HttpMessageConverter<?>>();
                        messageConverters.add(new FormHttpMessageConverter());
                        messageConverters.add(new StringHttpMessageConverter());
                        restTemplate.setMessageConverters(messageConverters);
                        		
                        restTemplate.setRequestFactory(new CommonsClientHttpRequestFactory());
                        String url = "http://10.1.1.1:9998/event/1";
                        String eventAsString = restTemplate.getForObject(url, String.class);
                        		
                        Event event = gson.fromJson(eventAsString, Event.class);
                        	
                        Log.d(TAG, "Result: [" + event + "]");
                        The org.json.* package does not have a serializer/deserializer so you have to go with something like GSON.

                        Comment


                        • #13
                          We cant go with just a JSON Object or HashMap, because we want to give those objects some more logic in form of additional methods.

                          Ok, it's good to know about GSON. But why are you not just using the method restTemplate.getForObject(url,Event.class) in combination with the JacksonJSONMessageConverter? RestTemplate provides all necessary utils.

                          Comment


                          • #14
                            Re: Examples to make RestTemplate work with JSON?

                            You can, or you can use one of six different scenarios to deserialize this response. It is all up to you want you want to use.

                            Perry Hoekstra

                            Comment

                            Working...
                            X