2016-08-22 64 views
3

我在Java 7中使用Gson解析器。我想將我的一個屬性保留爲原始JSON字符串,以便稍後將其反序列化到所需的類中。保留屬性的原始JSON字符串

示例輸入JSON:

{ 
    "foo":"bar", 
    "body":["blah"] 
} 

{ 
    "foo":"bar", 
    "body":{"a":"b"} 
} 

反序列化到這樣一類:

public class Message { 
    public String foo; 
    public String bar; //I want this to be a raw JSON string, not parsed 
} 

代碼:

String input = "{\"foo\":\"bar\", \"body\":[\"blah\"]}"; 

Message message = gson.fromJson(input, Message.class); 

message.foo; //"bar" 
message.body; //"[\"blah\"]" 

這可能嗎?

UPDATE:

我正在這樣做,但它會是很好,如果它可能是「乾淨」,並以某種方式使用本機String類型...

public class Message { 
    public String foo; 
    public JsonString body; 
} 

public static class JsonString { 
    public String body; 
} 

public static class JsonStringDeserializer implements JsonDeserializer<JsonString> { 
    @Override 
    public JsonString deserialize(JsonElement json, Type type, JsonDeserializationContext context) { 
     JsonString a = new JsonString(); 
     a.body = json.toString(); 
     return a; 
    } 
} 

事情我不「噸像這個是我必須使用反序列化對象,像這樣:

Message message = gson.fromJson(input, Message.class); 

//notice how i have to use the inner string 
SomeClass cls = gson.fromJson(message.body.body, SomeClass.class); 
+0

我會創建一個自定義註釋和我自己的類來實現'JsonDeserializer ';並以這種方式寫'deserialize'實現,以將'JsonElement'作爲'String'持久化。然後,您可以使用'GsonBuilder'的'registerTypeAdapter'來構造一個知道這個註解的'Gson'。 – jacob

+0

請看我更新的問題!我想我做了類似的事情,但它有點不受歡迎(儘管如此,也許是不可避免的)。 – tau

回答

1

如果你不介意聲明你body財產爲Object而不是String來解決JSON解碼問題;你可以做以下事情。對於JSONRawString

註釋定義:

import java.lang.annotation.ElementType; 
import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 
import java.lang.annotation.Target; 

@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.FIELD) 
public @interface JSONRawString { 
} 

Message類:

public class Message { 
    public String foo; 

    @JSONRawString 
    public Object body; 
} 

解串器:

public class JSONRawStringDeserializer<T> implements JsonDeserializer<T> { 
    @Override 
    public T deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException { 
     //We decode using the normal deserializer; but will run over all the fields and check if our annotation exists. This is a bit hacky; but should work if you don't mind declaring your objects which you'd like to maintain as deserialized as Object. 
     T serializedObject = new Gson().fromJson(jsonElement, type); 
     Field[] fields = serializedObject.getClass().getDeclaredFields(); 
     for (Field field : fields) { 
      if (field.getAnnotation(JSONRawString.class) != null) { 
       try { 
        String fieldName = field.getName(); 
        if(field.getAnnotation(SerializedName.class) != null) { 
         fieldName = field.getAnnotation(SerializedName.class).value(); 
        } 

        String element = new Gson().toJson(jsonElement.getAsJsonObject().get(fieldName).toString()); 
        field.set(serializedObject, element); 
       } catch(IllegalAccessException e) { 
        throw new JsonParseException(e); 
       } 
      } 
     } 

     return serializedObject; 
    } 
} 

最後在Main

import com.google.gson.Gson; 
import com.google.gson.GsonBuilder; 

public class Main { 

    public static void main(String[] args) { 
     Gson gson = new GsonBuilder() 
       .registerTypeAdapter(Message.class, new JSONRawStringDeserializer<Message>()) 
       .create(); 

     String input = "{\"foo\":\"bar\", \"body\":[\"blah\"]}"; 

     Message message = gson.fromJson(input, Message.class); 
     System.out.printf("message.foo: %s, message.body: %s", message.foo, message.body); 
    } 
} 

message.foo: bar, message.body: "[\"blah\"]"

這有點哈克所得;因爲我們忽略了Gson用我們自己的方法吐出來的東西;我不認爲這是遞歸的。希望它會引導你找到解決方案。

相關問題