2

使用 Java 6、Tomcat 7、Jersey 1.15、Jackson 2.0.6(来自 FasterXml maven repo)和 www.json.org 解析器,我试图漂亮地打印 JSON 字符串,因此它看起来会被 curl -X GET 命令缩进线。

我创建了一个简单的 Web 服务,它具有以下架构:

我的 POJO(模型类):

家庭.java

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Family {
    private String father;
    private String mother;

    private List<Children> children;

    // Getter & Setters
}

儿童.java

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Children {
    private String name;
    private String age;
    private String gender;

    // Getters & Setters
}

使用实用程序类,我决定对 POJO 进行硬编码,如下所示:

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;
    }
}

我的网络服务:

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);         
    }
}

当我使用以下命令运行它时:

curl -X GET http://localhost:8080/mywebservice

我在 Eclipse 的控制台中得到了这个:

{"father":"Joe","mother":"Jennifer","children":[{"name":"Jimmy","age":"12","gender":"male"}]}

但是从命令行上的 curl 命令(这个响应更重要):

"{\n    \"mother\": \"Jennifer\",\n    \"children\": [{\n        \"age\": \"12\",\n        \"name\": \"Jimmy\",\n        \"gender\": \"male\"\n    }],\n    \"father\": \"Joe\"\n}"

这是添加换行符转义序列并放置双引号(但不会像在新行之后确实有 4 个空格但都在一行中那样缩进)。

如果有人能指出我正确的方向,将不胜感激。

4

2 回答 2

4

我相信正在发生的是您当前配置的消息正文阅读器正在获取从您的方法返回的字符串,并将其正确转义,使其成为有效的 JSON 字符串(因为 json 不允许字符串常量内的换行符)。

这就是你要做的……我假设你正在使用 Jackson 包含的 Message Body Writers。(例如 JacksonJsonProvider)

您创建一个 @Provider 来设置一个启用漂亮打印的 ObjectMapper 实例,如下所示:

@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;
    }
}

然后,您让您的资源返回已解析的 Family 对象,而不是尝试将其转换为 Json...让 Message Body Writer 执行此操作...即

public class MyWebService {

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Family getFamily() 
        return FamilyUtil.getFamily()
    }
}

瞧:

$ curl http://<server>/<ctx-root>/<path>
{
  "father" : "Joe",
  "mother" : "Jennifer",
  "children" : [ {
    "name" : "Jimmy",
    "age" : "12",
    "gender" : "male"
  } ]
}

现在我忽略了让 Provider 和 MessageBodyReader 注册到您的 JAX-RS 应用程序配置,但这可能会因您使用 Jersey 的 servlet、使用自定义应用程序、使用 Guice 或任何其他设置方式而有很大差异你的 JAX-RS 堆栈。

于 2012-12-14T05:00:05.980 回答
1

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);

    }
}
于 2015-07-16T10:02:21.160 回答