2016-08-22 6 views
3

Java 7でGsonパーサを使用しています。後で目的のクラスに逆シリアル化できるように、自分のプロパティの1つを生の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; 
    } 
} 

事IドンこれについてLIKE」tは、私はそうのような非直列化オブジェクトを使用しなければならないことである。

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 'を実装する自分のクラスを作成したいと思います。 'JsonElement'を' String'として保持するように 'deserialize'実装を記述してください。 'GsonBuilder'の' registerTypeAdapter'を使い、このアノテーションを認識している 'Gson'を構築することができます。 – jacob

+0

私の更新された質問をご覧ください!私は似たようなことをやったと思いますが、それはやや望ましくないかもしれません。 – tau

答えて

1

あなたはとしてあなたbodyプロパティを宣言する気にしない場合JSONデコードの問題を回避するためにStringの代わりに210あなたは以下を行うことができます。 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; 
} 

デシリアライザ:Mainで最後に

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

これは一種のハックです message.foo: bar, message.body: "[\"blah\"]"

に結果の

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

。 Gsonが独自の方法で吐き出したものを無効にするからです。私はこれが再帰的に働くとは思わない。うまくいけば、それはあなたを解決策に導くでしょう。

関連する問題