Jackson JSONライブラリでJSONを既存のオブジェクトに逆シリアル化する方法を教えてください。これを行う方法を見つけようとしました。ただし、クラスを取得してそれ自体をインスタンス化することしかできないようです。
または、可能でない場合は、Java JSON逆シリアル化ライブラリがそれを実行できるかどうかを知りたいです。
これはC#の対応する質問のようです: JSON文字列から既存のオブジェクトインスタンスへのデータのオーバーレイ 。 JSON.NETにはPopulateObject(string、object)があるようです。
ジャクソンを使用してこれを行うことができます:
mapper.readerForUpdating(object).readValue(json);
Springフレームワークを使用している場合は、このタスクにBeanUtilsライブラリを使用できます。最初に通常どおりjson文字列をデシリアライズしてから、BeanUtilsを使用してこのオブジェクトを親オブジェクト内に設定します。また、オブジェクトの変数名が親オブジェクト内に設定されることも想定しています。これがコードスニペットです。
childObject = gson.fromJson("your json string",class.forName(argType))
BeanUtils.setProperty(mainObject, "childObjectName", childObject);
ジャクソンの代わりに別のライブラリを使用できる場合は、Genson http://owlike.github.io/genson/ を試すことができます。他のいくつかのニース機能(注釈のない空でないコンストラクターを使用したデシリアライズ、ポリモーフィック型へのデシリアライズなど)に加えて、既存のインスタンスへのJavaBeanのデシリアライズをサポートします。次に例を示します。
BeanDescriptorProvider provider = new Genson().getBeanDescriptorFactory();
BeanDescriptor<MyClass> descriptor = provider.provide(MyClass.class, genson);
ObjectReader reader = new JsonReader(jsonString);
MyClass existingObject = descriptor.deserialize(existingObject, reader, new Context(genson));
質問がある場合は、遠慮なくメーリングリスト http://groups.google.com/group/genson を使用してください。
あなたは私のリポジトリを使用することができます:)。
_Object yo = //yourObject
String js = //json source
Map remote = Object$.remoteMap(yo, false); //or you can use Bean.forInstance(yo);
Reader reader = new StringReader(js);//you can replace this with any reader :)
AtomicReference buffer = new AtomicReference(remote);
try {
JSON.global.parse(buffer, reader, null, null);
} catch (IOException ignored) {
//If any exception got thrown by the reader
}
_
このようにして、JSONは値を解析して、バッファー内で検出したマップにマッピングします。マップにリストが含まれていて、JSON値にもリストがある場合。マップ上のリストは置き換えられません。代わりに、値を含めるために使用されます。
Bean.forInstance(yo)
を使用した場合、返されるリモートマップにはいくつかの追加機能があります。
リポジトリ:
util repo(必須): _github.com/cufyorg/util
_
基本リポジトリ(必須): _github.com/cufyorg/base
_
JSONリポジトリ(必須): _github.com/cufyorg/json
_
beanリポジトリ(オプション): _github.com/cufyorg/beans
_
Jackson + SpringのDataBinderを使用して、このようなことを実現しました。このコードは配列を処理しますが、ネストされたオブジェクトは処理しません。
private void bindJSONToObject(Object obj, String json) throws IOException, JsonProcessingException {
MutablePropertyValues mpv = new MutablePropertyValues();
JsonNode rootNode = new ObjectMapper().readTree(json);
for (Iterator<Entry<String, JsonNode>> iter = rootNode.getFields(); iter.hasNext(); ) {
Entry<String, JsonNode> entry = iter.next();
String name = entry.getKey();
JsonNode node = entry.getValue();
if (node.isArray()) {
List<String> values = new ArrayList<String>();
for (JsonNode elem : node) {
values.add(elem.getTextValue());
}
mpv.addPropertyValue(name, values);
if (logger.isDebugEnabled()) {
logger.debug(name + "=" + ArrayUtils.toString(values));
}
}
else {
mpv.addPropertyValue(name, node.getTextValue());
if (logger.isDebugEnabled()) {
logger.debug(name + "=" + node.getTextValue());
}
}
}
DataBinder dataBinder = new DataBinder(obj);
dataBinder.bind(mpv);
}
flexJsonも同じことを行うのに役立ちます。
これは FlexJson Doc からコピーした例です
DeserializeInto関数は、文字列と既存のオブジェクトへの参照を取得します。
Person charlie = new Person("Charlie", "Hubbard", cal.getTime(), home, work );
Person charlieClone = new Person( "Chauncy", "Beauregard", null, null, null );
Phone fakePhone = new Phone( PhoneNumberType.MOBILE, "303 555 1234");
charlieClone.getPhones().add( fakePhone );
String json = new JSONSerializer().include("hobbies").exclude("firstname", "lastname").serialize( charlie );
Person p = new JSONDeserializer<Person>().deserializeInto(json, charlieClone);
Pに返される参照はcharlieCloneと同じで、値が更新されているだけです。
常にダミーオブジェクトにロードし、リフレクションを使用してデータを転送できます。あなたの心がGSONを使うだけの場合
例。このコードがデータをコピーしたいオブジェクトにあると仮定します
public void loadObject(){
Gson gson = new Gson();
//make temp object
YourObject tempStorage = (YourObject) gson.fromJson(new FileReader(theJsonFile), YourObject.class);
//get the fields for that class
ArrayList<Field> tempFields = new ArrayList<Field>();
ArrayList<Field> ourFields = new ArrayList<Field>();
getAllFields(tempFields, tempStorage.getClass());
getAllFields(thisObjectsFields, this.getClass());
for(Field f1 : tempFields){
for(Field f2 : thisObjectsFields){
//find matching fields
if(f1.getName().equals(f2.getName()) && f1.getType().equals(f2.getType())){
//transient and statics dont get serialized and deserialized.
if(!Modifier.isTransient(f1.getModifiers())&&!Modifier.isStatic(f1.getModifiers())){
//make sure its a loadable thing
f2.set(this, f1.get(tempStorage));
}
}
}
}
}
public static List<Field> getAllFields(List<Field> fields, Class<?> type) {
for (Field field : type.getDeclaredFields()) {
fields.add(field);
}
if (type.getSuperclass() != null) {
fields = getAllFields(fields, type.getSuperclass());
}
return fields;
}
1つの解決策は、新しいオブジェクトグラフ/ツリーを解析してから、既存のオブジェクトグラフ/ツリーに統合コピーすることです。ただし、特に型情報の可用性が低いために具象型が異なる場合は、効率が低下し、作業が増えます。 (実際には答えではありません。もっと良い答えがあるといいのですが、他の人がこのように答えることを避けたいだけです。)