【问题标题】:How to ask gson to avoid escaping json in a json response?如何让 gson 避免在 json 响应中转义 json?
【发布时间】:2015-12-08 22:36:28
【问题描述】:

我有一个这样的响应对象:

public class TestResponse {

    private final String response;
    private final ErrorCodeEnum error;
    private final StatusCodeEnum status;

    // .. constructors and getters here
}

我正在使用 Gson 库对上面的类进行序列化,如下所示:

Gson gson = new GsonBuilder().setPrettyPrinting().serializeNulls().create();
System.out.println(gson.toJson(testResponseOutput));

我得到的回复如下所示:

{
  "response": "{\"hello\":0,\"world\":\"0\"}",
  "error": "OK",
  "status": "SUCCESS"
}

如您所见,"response" 字段中的我的 json 字符串正在转义。有什么办法可以让 gson 不要这样做,而是返回一个完整的响应,如下所示:

{
  "response": {"hello":0,"world":"0"},
  "error": "OK",
  "status": "SUCCESS"
}

还有——如果我按照上面的方式做会有什么问题吗?

注意:我的 "response" 字符串将始终是 JSON 字符串,否则它将为空,因此我的 "response" 字符串中只有这两个值。在"response" 字段中,我可以有任何json 字符串,因为这个库正在调用一个可以返回任何json 字符串的rest 服务,所以我将它存储在一个字符串"response" 字段中。

【问题讨论】:

  • 你找到这个问题的合适答案了吗?
  • @nickb 我想还没有。如果您有任何问题,请随时写一个答案。可能对我有帮助吗?
  • 当然,你试过my answer below吗?它应该适用于任意 JSON!

标签: java json gson


【解决方案1】:

如果您的 response 字段可以是任意 JSON,那么您需要:

  1. 将其定义为任意 JSON 字段(利用 GS​​ON 中已内置的 JSON 类型系统,将其定义为 JSON 层次结构的根 - JsonElement

    public class TestResponse {
        private final JsonElement response;
    }
    
  2. String 字段转换为适当的 JSON 对象表示。为此,您可以使用 GSON 的 JsonParser 类:

    final JsonParser parser = new JsonParser();
    
    String responseJson = "{\"hello\":0,\"world\":\"0\"}";
    JsonElement json = parser.parse(responseJson); // Omits error checking, what if responseJson is invalid JSON?
    System.out.println(gson.toJson(new TestResponse(json)));
    

这应该打印出来:

{
  "response": {
    "hello": 0,
    "world": "0"
  }
}

它也应该适用于任何有效的 JSON:

String responseJson = "{\"arbitrary\":\"fields\",\"can-be\":{\"in\":[\"here\",\"!\"]}}";
JsonElement json = parser.parse(responseJson);
System.out.println(gson.toJson(new TestResponse(json)));

输出:

{
  "response": {
    "arbitrary": "fields",
    "can-be": {
      "in": [
        "here",
        "!"
      ]
    }
  }
}

【讨论】:

  • 也适合我。谢谢!
【解决方案2】:

我知道这是旧的,但只是添加一个潜在的答案以备不时之需。

听起来您只想返回响应而不转义。转义是个好东西,它有助于防止安全问题,防止你的 JS 应用程序因错误而崩溃。

但是,如果您仍然想忽略转义,请尝试:

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

【讨论】:

    【解决方案3】:

    添加简单的 TypeAdapter 并使用 jsonValue(value) gson 2.8.0

    版本 1:

      @Test
    public void correctlyShow() {
        TestResponse2 src = new TestResponse2("{\"arbitrary\":\"fields\",\"can-be\":{\"in\":[\"here\",\"!\"]}}");
        Gson create = new GsonBuilder().registerTypeAdapter(String.class, ADAPTER).create();
    
        Stopwatch createStarted = Stopwatch.createStarted();
        String json2 = create.toJson(src);
        System.out.println(json2 + " correctlyShow4 " + createStarted.stop());
    }
    
    public class TestResponse2 {
        private final String response;
    
        public TestResponse2(String response) {
            this.response = response;
        }
    
        public String getResponse() {
            return response;
        }
    }
    
    private static final TypeAdapter<String> ADAPTER = new TypeAdapter<String>() {
        @Override
        public String read(JsonReader in) throws IOException {
            throw new UnsupportedOperationException("Unsupported Operation !!!");
        }
    
        @Override
        public void write(JsonWriter out, String value) throws IOException {
            out.jsonValue(value);
        }
    };
    

    ...

    版本 2

    @Test
    public void correctlyShow() {
        TestResponse2 src = new TestResponse2("{\"arbitrary\":\"fields\",\"can-be\":{\"in\":[\"here\",\"!\"]}}");
    
        String json2 = new Gson().toJson(src);
        System.out.println(json2 + " correctlyShow4 ");
    }
    
    public class TestResponse2 {
        @JsonAdapter(value = AdapterStringJson.class)
        private final String response;
    
        public TestResponse2(String response) {
            this.response = response;
        }
    
        public String getResponse() {
            return response;
        }
    }
    
    private class AdapterStringJson extends TypeAdapter<String> {
        @Override
        public String read(JsonReader in) throws IOException {
            throw new UnsupportedOperationException("Unsupported Operation !!!");
        }
    
        @Override
        public void write(JsonWriter out, String value) throws IOException {
            out.jsonValue(value);
        }
    }
    

    【讨论】:

    • 我在 javadocs 中看到了它,但它似乎没有解决,我也无法在源代码中找到对它的任何引用。这被删除了吗?
    【解决方案4】:

    你应该有一个嵌套对象。

    public class Response {
        private final Integer hello;
        private final String world;
    }
    
    public class TestResponse {
        private final Response response;
        private final ErrorCodeEnum error;
        private final StatusCodeEnum status;
    
        // .. constructors and getters here
    }
    

    【讨论】:

    • 它并不总是你好和世界。我正在从另一个服务的响应字段中获取我的 JSON 字符串。所以在响应字段中它可以是任何 JSON 字符串。
    • 所以,你需要想办法将json字符串解析为对象。也许这个链接可以帮助你。 stackoverflow.com/questions/2591098/how-to-parse-json-in-java
    【解决方案5】:

    根据您的需要,您可以使用地图(或类似的)或嵌套对象来代替字符串。以这种方式表示它应该没有问题,但在您的示例中,如果它是一个字符串,如果您没有转义诸如双引号之类的字符,则会出现问题。

    【讨论】:

      猜你喜欢
      • 2018-09-12
      • 2013-03-07
      • 1970-01-01
      • 2019-11-10
      • 1970-01-01
      • 2021-12-02
      • 2020-02-05
      • 2019-05-19
      • 2021-09-11
      相关资源
      最近更新 更多