9

I have a response object like this:

public class TestResponse {

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

    // .. constructors and getters here
}

I am serializing above class using Gson library as shown below:

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

And the response I am getting back is shown below:

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

As you can see, my json string in "response" field is getting escaped. Is there any way I can ask gson not to do that and instead return a full response like this:

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

And also - Is there any problem if I do it above way?

NOTE: My "response" string will always be JSON string or it will be null so only these two values will be there in my "response" string. In "response" field, I can have any json string since this library is calling a rest service which can return back any json string so I am storing that in a string "response" field.

john
  • 11,311
  • 40
  • 131
  • 251
  • Did you find a suitable answer to this question? – nickb Dec 21 '15 at 14:51
  • @nickb I guess not yet.. If you have anything please feel free to write an answer.. May be that can help me a bit? – john Dec 22 '15 at 06:17
  • Sure, did you try out [my answer below](http://stackoverflow.com/a/34181429/862594)? It should work for any arbitrary JSON! – nickb Dec 22 '15 at 14:25

6 Answers6

14

If your response field can be arbitrary JSON, then you need to:

  1. Define it as an arbitrary JSON field (leveraging the JSON type system already built into GSON by defining it as the root of the JSON hierarchy - JsonElement)

    public class TestResponse {
        private final JsonElement response;
    }
    
  2. Convert the String field to an appropriate JSON object representation. For this, you can use GSON's JsonParser class:

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

This should print:

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

It should also work for any valid JSON:

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

Output:

{
  "response": {
    "arbitrary": "fields",
    "can-be": {
      "in": [
        "here",
        "!"
      ]
    }
  }
}
nickb
  • 59,313
  • 13
  • 108
  • 143
3

I know this is old but just adding an potential answer in case it is needed.

Sounds like you just want to return the response without escaping. Escaping is a good thing, it will help to prevent security issues and prevent your JS application from crashing with errors.

However, if you still want to ignore escaping, try:

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

DaviesTobi alex
  • 610
  • 1
  • 9
  • 34
james
  • 601
  • 1
  • 7
  • 12
1

add simple TypeAdapter and use jsonValue(value) gson 2.8.0

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

...

vesrion 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);
    }
}
DEV-Jacol
  • 567
  • 3
  • 10
  • I see it in the javadocs, but it doesn't appear to resolve, nor can I find any reference to it in the source. Did this get removed? – topher217 Apr 01 '21 at 05:02
0

You should have a nested object.

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
}
  • It's not always hello and world. I am getting my JSON string which is in response field from another service. So in the response field it can be any JSON string. – john Dec 08 '15 at 22:52
  • So, you need to find a way to parse the json string as an object. Maybe this link can help you. http://stackoverflow.com/questions/2591098/how-to-parse-json-in-java – Danny Fardy Jhonston Bermúdez Dec 08 '15 at 23:01
0

The below code is avoiding escape characters. Use getAsString method.

jsonElementEntry.getValue().getAsString()


    JsonObject jsonObjectResponse = new JsonObject();
    String jsonResponseProcessed = null;
    try {
        Gson gson = new Gson();
        JsonObject jsonObject = gson.fromJson(jsonString, JsonObject.class);
        for (Map.Entry<String, JsonElement> jsonElementEntry : jsonObject.entrySet()) {
            String jsonElementEntryKey = jsonElementEntry.getKey();
            if (jsonElementEntryKey == null)    continue;
            boolean isIgnoreProperty = false;
            for (String ignorePropertyStr : IGNORE_JOB_PARAMETERS_LIST) {
                if (jsonElementEntryKey.startsWith(ignorePropertyStr)) {
                    isIgnoreProperty = true;
                    break;
                }
            }
            if (!isIgnoreProperty){
                jsonObjectResponse.addProperty(jsonElementEntryKey, jsonElementEntry.getValue().getAsString());
            }
        }
-1

Instead of a String, depending on your needs, you could use a Map (or similar) or a nested Object. There should not be a problem representing it this way but in your example, if it were a String, there would be a problem if you didn't escape characters such as the double-quote.

Eric Wilk
  • 59
  • 2