Reputation: 5374
Using Java 6, Tomcat 7, Jersey 1.15, Jackson 2.0.6 (from FasterXml maven repo), & www.json.org parser, I am trying to pretty print the JSON String so it will look indented by the curl -X GET command line.
I created a simple web service which has the following architecture:
My POJOs (model classes):
Family.java
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Family {
private String father;
private String mother;
private List<Children> children;
// Getter & Setters
}
Children.java
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Children {
private String name;
private String age;
private String gender;
// Getters & Setters
}
Using a Utility Class, I decided to hard code the POJOs as follows:
public class FamilyUtil {
public static Family getFamily() {
Family family = new Family();
family.setFather("Joe");
family.setMother("Jennifer");
Children child = new Children();
child.setName("Jimmy");
child.setAge("12");
child.setGender("male");
List<Children> children = new ArrayList<Children>();
children.add(child);
family.setChildren(children);
return family;
}
}
My web service:
import java.io.IOException;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jettison.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;
import com.myapp.controller.myappController;
import com.myapp.resource.output.HostingSegmentOutput;
import com.myapp.util.FamilyUtil;
@Path("")
public class MyWebService {
@GET
@Produces(MediaType.APPLICATION_JSON)
public static String getFamily() throws IOException,
JsonGenerationException,
JsonMappingException,
JSONException,
org.json.JSONException {
ObjectMapper mapper = new ObjectMapper();
String uglyJsonString = mapper.writeValueAsString(FamilyUtil.getFamily());
System.out.println(uglyJsonString);
JSONTokener tokener = new JSONTokener(uglyJsonString);
JSONObject finalResult = new JSONObject(tokener);
return finalResult.toString(4);
}
}
When I run this using:
curl -X GET http://localhost:8080/mywebservice
I get this in my Eclipse's console:
{"father":"Joe","mother":"Jennifer","children":[{"name":"Jimmy","age":"12","gender":"male"}]}
But from the curl command on the command line (this response is more important):
"{\n \"mother\": \"Jennifer\",\n \"children\": [{\n \"age\": \"12\",\n \"name\": \"Jimmy\",\n \"gender\": \"male\"\n }],\n \"father\": \"Joe\"\n}"
This is adding newline escape sequences and placing double quotes (but not indenting like it should it does have 4 spaces after the new line but its all in one line).
Would appreciate it if someone could point me in the right direction.
Upvotes: 3
Views: 5453
Reputation: 1632
Just use GSON library
This is an example for Jersey normal Gson:
Gson gson = new Gson();
String json = gson.toJson(obj);
System.out.println(json);
the JSON output is display as compact mode like following :
{"data1":100,"data2":"hello","list":["String 1","String 2","String 3"]}
To enable pretty print, you should use GsonBuilder return a Gson object :
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String json = gson.toJson(obj);
System.out.println(json);
Output will like this:
{
"data1": 100,
"data2": "hello",
"list": [
"String 1",
"String 2",
"String 3"
]
}
Full example from mkyong
package com.mkyong.core;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
public class GsonExample {
public static void main(String[] args) {
DataObject obj = new DataObject();
// Gson gson = new Gson();
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String json = gson.toJson(obj);
System.out.println(json);
}
}
Upvotes: 1
Reputation: 7349
What I believe is happening is your currently configured message body reader is taking your String returned from your method, and escaping it properly so that it is a valid JSON string (since json doesn't let newlines inside of string constants).
Here's what you do... I'm assuming that you are using Jackson's included Message Body Writers. (e.g. JacksonJsonProvider)
You create a @Provider that sets up an ObjectMapper instance with Pretty Printing enabled like so:
@Provider
public class JacksonObjectMapperProvider implements ContextResolver<ObjectMapper> {
/**
* {@inheritDoc}
*/
@Override
public ObjectMapper getContext(final Class<?> type) {
final ObjectMapper toReturn = new ObjectMapper();
toReturn.enable(SerializationFeature.INDENT_OUTPUT); // This is the important setting
toReturn.disable(MapperFeature.USE_ANNOTATIONS); // I have this one on but it's probably for other resources in the container testing it in, I don't know if you'd need it.
return toReturn;
}
}
You then have your Resource return the resolved Family object instead of trying to transform it to Json... let the Message Body Writer do that... i.e.
public class MyWebService {
@GET
@Produces(MediaType.APPLICATION_JSON)
public Family getFamily()
return FamilyUtil.getFamily()
}
}
and Voila:
$ curl http://<server>/<ctx-root>/<path>
{
"father" : "Joe",
"mother" : "Jennifer",
"children" : [ {
"name" : "Jimmy",
"age" : "12",
"gender" : "male"
} ]
}
Now I glossed over getting the Provider and MessageBodyReader registered with your JAX-RS Application configuration, but that could vary greatly depending upon if you're using Jersey's servlet, using a custom Application, using Guice, or any number of other ways of setting up your JAX-RS stack.
Upvotes: 4