Java 防止GSON序列化JSON字符串
我是gson的新手,有一个新问题我还没有找到答案,所以请容忍我。StackOverflow和google不是我的朋友:( 我有一个java类“User”,它的一个属性“externalProfile”是一个包含已序列化JSON的java字符串。当gson序列化用户对象时,它会将externalProfile视为原语,从而通过添加额外的斜杠等来逃避JSON。 我希望gson不使用这个字符串,只使用“原样”,因为它已经是有效和可用的JSON 为了区分JSON字符串,我创建了一个名为JSONString的简单类,并尝试使用reader/Writer、registerTypeAdapter,但没有任何效果。 你能帮我吗Java 防止GSON序列化JSON字符串,java,json,serialization,gson,Java,Json,Serialization,Gson,我是gson的新手,有一个新问题我还没有找到答案,所以请容忍我。StackOverflow和google不是我的朋友:( 我有一个java类“User”,它的一个属性“externalProfile”是一个包含已序列化JSON的java字符串。当gson序列化用户对象时,它会将externalProfile视为原语,从而通过添加额外的斜杠等来逃避JSON。 我希望gson不使用这个字符串,只使用“原样”,因为它已经是有效和可用的JSON 为了区分JSON字符串,我创建了一个名为JSONStrin
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);
}
在我将其作为JSONString存储在User对象中,并将User对象转换为JSON之后:
User user = new User();
user.setExternalProfile(new JSONString(externalProfile)),
String json = customJsonBuilder(user);
json将包含以下内容:
{\"profile\":{\"registrationNumber\": 11111}}
因此,gson将externalProfile JSONString序列化为字符串原语,在双引号前面添加额外的斜杠。
我希望gson将这个JSONString保持原样,因为它已经是可用的JSON了。
我正在寻找一个类型适配器/读写器来完成这项工作,但我无法让它工作。正如Alexis C所述: 首先将externalProfile存储为JsonObject:
new Gson().fromJson(externalProfile, JsonObject.class));
并让gson在输出用户对象时再次序列化它。
将生成完全相同的JSON!我解决了它,没有进行不必要的反序列化。创建类:
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
}
}
就是这样。正常使用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);
}
}
}
公共类RawJsonGsonAdapter扩展了TypeAdapter{
@凌驾
公共void write(最终JsonWriter out,最终字符串值)抛出IOException{
out.jsonValue(value);
}
@凌驾
公共字符串读取(中的最终JsonReader)引发IOException{
var sb=新的StringBuilder();
int n=0;
虽然(正确){
开关(in.peek()){
案例开始\u数组:
in.beginArray();
某人加上(“[”);
打破
案例开始对象:
in.beginObject();
某人附加(“{”);
n++;
打破
大小写布尔值:
sb.append(in.nextBoolean()).append(“,”);
打破
案例结束单元阵列:
(某人);
in.endArray();
某人加上(“]”);
打破
案例结束文件:
抛出新的RuntimeException(“END_DOCUMENT invalid here”);
案例结束对象:
(某人);
in.endObject();
某人附加(“}”);
如果(--n==0)
使某人返回字符串();
打破
案例名称:
sb.append(“\”).append(in.nextName()).append(“\”:”);
打破
大小写为空:
in.nextNull();
某人加上(“”);
打破
案件编号:
试一试{
sb.append(in.nextInt()).append(“,”);
打破
}捕获(异常e1){
试一试{
sb.append(in.nextLong()).append(“,”);
打破
}捕获(异常e2){
sb.append(in.nextDouble()).append(“,”);
打破
}
}
大小写字符串:
sb.append(“\”).append(in.nextString()).append(“\”,”);
打破
}
}
}
私有void dropLastComma(StringBuilder sb){
如果(sb.charAt(sb.length()-1)==','){
sb.setLength(sb.length()-1);
}
}
}
是否可以有一个输入示例,这样我们就可以重现并尝试解决您的问题?嗨@Alexis C.,我已将其添加到我的初始问题中。谢谢!您签出了吗?是的,我签了@Reek,但我确实希望响应中包含externalProfile!因此它应该是对象序列化输出的一部分,但我希望gson将其保留为al一个(防止双重序列化)。嗯,一个肮脏的解决方案可能是首先排除该属性,然后手动将其添加到序列化响应。或者,首先反序列化externalProfile,然后序列化User?
public class MyPojo {
@JsonAdapter(RawJsonGsonAdapter.class)
public String someJsonInAString;
public String normalString;
}
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);
}
}
}