阻止 GSON 序列化 JSON 字符串
Prevent GSON from serializing JSON string
我是 gson 的新手,有一个 newby 问题我还没有找到答案,所以请多多包涵。 Whosebug 和 google 不是我的朋友 :(
我有一个 java class "User",它的一个属性 "externalProfile" 是一个 Java 包含已经序列化的字符串 JSON.当 gson 序列化 User 对象时,它会将 externalProfile 视为原始类型,从而转义 JSON 添加额外的斜杠等。
我希望 gson 不理会字符串,只使用它 "as is",因为它已经有效且可用 JSON.
为了区分 JSON 字符串,我创建了一个名为 JSONString 的简单 class,我尝试使用 reader/writers、registerTypeAdapter,但没有任何效果。
你能帮帮我吗?
public class User {
private JSONString externalProfile;
public void setExternalProfile(JSONString externalProfile) { this.externalProfile = externalProfile; }
}
public final class JSONString {
private String simpleString;
public JSONString(String simpleString) { this.simpleString = simpleString; }
}
public customJsonBuilder(Object object) {
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(GregorianCalendar.class, new JsonSerializer<GregorianCalendar>() {
public JsonElement serialize(GregorianCalendar src, Type type, JsonSerializationContext context) {
if (src == null) {
return null;
}
return new JsonPrimitive(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(src.getTime()));
}
});
Gson gson = builder.create();
return gson.toJson(object);
}
例如,externalProfile 将保存(作为字符串值):
{"profile":{"registrationNumber": 11111}}
在我将其作为JSONString 存储在User 对象中之后,我们将用户对象转换为JSON:
User user = new User();
user.setExternalProfile(new JSONString(externalProfile)),
String json = customJsonBuilder(user);
json 会像这样:
{\"profile\":{\"registrationNumber\": 11111}}
因此,externalProfile JSONString 被 gson 序列化为 String primitive,在双引号前面添加了额外的斜杠。
我希望 gson 保留此 JSONString 原样,因为它已经可用 JSON。
我正在寻找类型适配器/reader-writer 来执行此操作,但我无法让它工作。
正如 Alexis C 所述:
首先将 externalProfile 存储为 JsonObject:
new Gson().fromJson(externalProfile, JsonObject.class));
并且让gson在输出User对象的时候再序列化这个。
会产生完全一样的JSON!
我在没有不必要的反序列化-序列化的情况下解决了它。创建 class:
public class RawJsonGsonAdapter extends TypeAdapter<String> {
@Override
public void write(final JsonWriter out, final String value) throws IOException {
out.jsonValue(value);
}
@Override
public String read(final JsonReader in) throws IOException {
return null; // Not supported
}
}
并在需要的地方通过注释使用它。例如:
public class MyPojo {
@JsonAdapter(RawJsonGsonAdapter.class)
public String someJsonInAString;
public String normalString;
}
就是这样。正常使用 Gson。
添加读取方法。
public class RawJsonGsonAdapter extends TypeAdapter<String> {
@Override
public void write(final JsonWriter out, final String value) throws IOException {
out.jsonValue(value);
}
@Override
public String read(final JsonReader in) throws IOException {
var sb = new StringBuilder();
int n = 0;
while (true) {
switch (in.peek()) {
case BEGIN_ARRAY:
in.beginArray();
sb.append("[");
break;
case BEGIN_OBJECT:
in.beginObject();
sb.append("{");
n++;
break;
case BOOLEAN:
sb.append(in.nextBoolean()).append(",");
break;
case END_ARRAY:
dropLastComma(sb);
in.endArray();
sb.append("]");
break;
case END_DOCUMENT:
throw new RuntimeException("END_DOCUMENT invalid here");
case END_OBJECT:
dropLastComma(sb);
in.endObject();
sb.append("}");
if (--n == 0)
return sb.toString();
break;
case NAME:
sb.append("\"").append(in.nextName()).append("\":");
break;
case NULL:
in.nextNull();
sb.append("");
break;
case NUMBER:
try {
sb.append(in.nextInt()).append(",");
break;
} catch (Exception e1) {
try {
sb.append(in.nextLong()).append(",");
break;
} catch (Exception e2) {
sb.append(in.nextDouble()).append(",");
break;
}
}
case STRING:
sb.append("\"").append(in.nextString()).append("\",");
break;
}
}
}
private void dropLastComma(StringBuilder sb) {
if (sb.charAt(sb.length() - 1) == ',') {
sb.setLength(sb.length() - 1);
}
}
}
我是 gson 的新手,有一个 newby 问题我还没有找到答案,所以请多多包涵。 Whosebug 和 google 不是我的朋友 :(
我有一个 java class "User",它的一个属性 "externalProfile" 是一个 Java 包含已经序列化的字符串 JSON.当 gson 序列化 User 对象时,它会将 externalProfile 视为原始类型,从而转义 JSON 添加额外的斜杠等。 我希望 gson 不理会字符串,只使用它 "as is",因为它已经有效且可用 JSON.
为了区分 JSON 字符串,我创建了一个名为 JSONString 的简单 class,我尝试使用 reader/writers、registerTypeAdapter,但没有任何效果。 你能帮帮我吗?
public class User {
private JSONString externalProfile;
public void setExternalProfile(JSONString externalProfile) { this.externalProfile = externalProfile; }
}
public final class JSONString {
private String simpleString;
public JSONString(String simpleString) { this.simpleString = simpleString; }
}
public customJsonBuilder(Object object) {
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(GregorianCalendar.class, new JsonSerializer<GregorianCalendar>() {
public JsonElement serialize(GregorianCalendar src, Type type, JsonSerializationContext context) {
if (src == null) {
return null;
}
return new JsonPrimitive(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(src.getTime()));
}
});
Gson gson = builder.create();
return gson.toJson(object);
}
例如,externalProfile 将保存(作为字符串值):
{"profile":{"registrationNumber": 11111}}
在我将其作为JSONString 存储在User 对象中之后,我们将用户对象转换为JSON:
User user = new User();
user.setExternalProfile(new JSONString(externalProfile)),
String json = customJsonBuilder(user);
json 会像这样:
{\"profile\":{\"registrationNumber\": 11111}}
因此,externalProfile JSONString 被 gson 序列化为 String primitive,在双引号前面添加了额外的斜杠。 我希望 gson 保留此 JSONString 原样,因为它已经可用 JSON。 我正在寻找类型适配器/reader-writer 来执行此操作,但我无法让它工作。
正如 Alexis C 所述:
首先将 externalProfile 存储为 JsonObject:
new Gson().fromJson(externalProfile, JsonObject.class));
并且让gson在输出User对象的时候再序列化这个。 会产生完全一样的JSON!
我在没有不必要的反序列化-序列化的情况下解决了它。创建 class:
public class RawJsonGsonAdapter extends TypeAdapter<String> {
@Override
public void write(final JsonWriter out, final String value) throws IOException {
out.jsonValue(value);
}
@Override
public String read(final JsonReader in) throws IOException {
return null; // Not supported
}
}
并在需要的地方通过注释使用它。例如:
public class MyPojo {
@JsonAdapter(RawJsonGsonAdapter.class)
public String someJsonInAString;
public String normalString;
}
就是这样。正常使用 Gson。
添加读取方法。
public class RawJsonGsonAdapter extends TypeAdapter<String> {
@Override
public void write(final JsonWriter out, final String value) throws IOException {
out.jsonValue(value);
}
@Override
public String read(final JsonReader in) throws IOException {
var sb = new StringBuilder();
int n = 0;
while (true) {
switch (in.peek()) {
case BEGIN_ARRAY:
in.beginArray();
sb.append("[");
break;
case BEGIN_OBJECT:
in.beginObject();
sb.append("{");
n++;
break;
case BOOLEAN:
sb.append(in.nextBoolean()).append(",");
break;
case END_ARRAY:
dropLastComma(sb);
in.endArray();
sb.append("]");
break;
case END_DOCUMENT:
throw new RuntimeException("END_DOCUMENT invalid here");
case END_OBJECT:
dropLastComma(sb);
in.endObject();
sb.append("}");
if (--n == 0)
return sb.toString();
break;
case NAME:
sb.append("\"").append(in.nextName()).append("\":");
break;
case NULL:
in.nextNull();
sb.append("");
break;
case NUMBER:
try {
sb.append(in.nextInt()).append(",");
break;
} catch (Exception e1) {
try {
sb.append(in.nextLong()).append(",");
break;
} catch (Exception e2) {
sb.append(in.nextDouble()).append(",");
break;
}
}
case STRING:
sb.append("\"").append(in.nextString()).append("\",");
break;
}
}
}
private void dropLastComma(StringBuilder sb) {
if (sb.charAt(sb.length() - 1) == ',') {
sb.setLength(sb.length() - 1);
}
}
}