2009-04-07 18 views
3

コンテキストの場合、ほとんどのデータはJSON文字列として格納されています。これはバックエンドのHadoopでうまく動作し、フロントエンドのRubyで扱いやすくなります。私のデータ型は、継承のための自然なパターンに適合しています。JavaとRubyを使用したJSONの多態性または継承

簡単にするために、私はクラスPetと、ペットに給餌するプロセスFeedPetを持っているとしましょう。私はまたペットの一種である犬にのみ適用されるプロセスWalkDogを持っています。私のデータは、私が犬ではないペットを歩くことを心配する必要がないように編成されています。

私がしたいのは、ペットと犬がペットを拡張し、犬が追加のメソッド "getLeash()"を持っていることですが、これをJSONにどのようにマッピングするかを理解できません。

代わりに、私は種データハッシュマップを持つクラスを持っているので、WalkDogプロセスはdog.getLeash()の代わりにpet.getSpeciesData( "leash")を呼び出します。

Dogを拡張することができます。私は、Jacksonライブラリを使用してJSONにそれをシリアル化できます。 JSONオブジェクトにはリースフィールドがあります。しかし、私はすべてのペットに餌を与えたいと仮定します。すべてのペットはgetFood()メソッドを持っています。そのため、FeedPetプロセスはオブジェクトをペットに逆シリアル化します。しかし、これはリーシュフィールドを失う。

WalkDogプロセスは、すべての入力がDogsになることを知っているので、これを行うことができます。そのため、Dogとして読み取ってDogとして書き戻すことができます。

JavaオブジェクトをJSONにシリアライズしてそのタイプを保持できる方法はありますか?私はRailsの単一のテーブル継承のようなものを考えていますが、JSONライブラリが理解できるものでなければなりません。

答えて

2

データ型の情報(デシリアライズにのみ役立つ)にはオブジェクト型情報を埋め込む必要がありますが、通常は外部スキーマ定義を使用する必要があります(XML Schema for XMLのように)。ジェネリック型システム)。 これはORMと同じ問題があります:Hibernateは醜い回避策(n + 1-wayジョイン、 "スーパーテーブル"またはdiscriminatorフィールド)を使用する必要があります。

他の方法:データマッピング/バインディングは、オブジェクトの直列化/逆シリアル化とは全く異なりません(後者はオブジェクトのアイデンティティをより多く保持しようとします)。

ここで私は何をしたいことは、基本的のようなものであると仮定しています:これに該当しない場合、あなたは単にとにかく犬

Dog dog = mapper.readValue(jsonString, Dog.class); 

を結合することができる

Pet pet = mapper.readValue(jsonString, Pet.class); 
// (and possibly get an exception if Pet is an abstract class...) 
Leash l = ((Dog) pet).getLeash(); 

:ジャクソンプロジェクトをfeature request for doing just thisを持っているので、あなたが望むものを(私が思う)できるようにすることができます。

しかし、このソリューションは、JSON内でオブジェクト型情報を渡す標準的な方法がないため、ほとんどの場合Java用に機能します。 XMLでは、これはXMLスキーマで定義された「xsi:type」属性でソートできます。スキーマのタイプを識別し、クラスにマップします(はい、複雑な方法ですが、機能します)。

UPDATEJackson 1.5(すなわちJACKSON-91機能要求を実現)、このためのサポートを追加し、多型のタイプの適切な取り扱いを可能にするために、生成タイプ識別子のために使用することができます。タイプ情報の組み込み方法の詳細を完全に構成できるので、Java以外のシステムでも動作するはずです。 Javaクラス名の使用に限定されません。

+0

私はあなたがそのコアに答えたと思いますが、JSONでこれを表現する標準的な方法はありません。 JACKSON-91は私の望むものを私に与えてくれます。私の場合、私はRubyのデータだけを読んでいるからです。 –

+0

ああ。実際には、Javaで読む必要がある場合にのみ91が必要になります。クラス情報を書くには簡単な方法があるかもしれませんが(91でもこれを明らかにカバーします) 1つの方法は、Object.getClass()を直列化可能にすることです(SerializationConfig.Feature.OUTPUT_CLASS_NAME?)。 – StaxMan

0

私は、JSONをdjangoのフィクスチャー以外で使用したことはあまりありませんでしたが、その場合は関連する値を持つ「モデル」キーしかありません。

オブジェクトのタイプと継承階層を決定するのは、オブジェクトを解釈するプログラムによって異なります。

私が言うことは、どのメソッドが使用可能でないかということです。これは、シリアル化する必要がないためです。オブジェクトの名前と属性のみ。

- あなたのプロセスではなく、実際のクラスよりも、親クラスにdeserialisingされるように、再びあなたの質問を読んだ後

を更新し、それはそうです。あなたの犬のクラスはペットから継承しているので、あなたはあなたのデシリアライザーが最も専門的なクラスのオブジェクトを作成していることを確認したいだけです。

私はJacksonのライブラリについてはわかりませんが、モデルフィールドのタイプを設定することができれば、それは動くかもしれません。

関連する問題