1

現在、Groovy JsonBuilderに問題があります。シリアル化しようとしているオブジェクトのプロパティは、一見ランダムな順序で出てきます。

オブジェクトのクラスは次のとおりです。

class Game {
    String title
    String gameImg2
    String description
}

そして、これは私が使用しているコードです:

def game = new Game(title: "a game", gameImg2: "an image", description: "desc")
def json = new JsonBuilder(game)

これから、出力は次のようになると思います。

{"title":"a game","gameImg2":"an image", "description":"desc"}

しかし、代わりに、私は得ています:

{"gameImg2":"gameImg","title":"hello","description":"desc"}.

JsonBuilderのサンプルコードを見ると、順序を維持する必要があるようです。実際、toJsonメソッドはLinkedHashMapであるobject.propertiesを反復処理しているように見えます。これは、クラスで宣言されている順序でプロパティを通過すると思いました。

私の推測では、これはゲームオブジェクトの初期化と関係があります。マップ構文を使用してプロパティを何らかの方法で割り当てることができますが、これも、順序を保持するLinkedHashMapを作成するようです。

誰かが私がここで間違ってまたは間違って仮定した可能性があることのインクリングを持っていますか?どんなリードも大きな助けになるでしょう!

4

1 に答える 1

6

問題は、オブジェクトをJSONにシリアル化することです。オブジェクトには、Javaに変換されるフィールドが宣言されています。

Javaでは、宣言の順序でフィールドをトラバースすることは(簡単に)不可能であり、JsonBuilderコードはこの動作を許可しようとはしません。

JsonBuilderのソースコードを見ると、JsonOutput.groovyというクラスを使用して、渡すオブジェクトを次のようにシリアル化することがわかります。

static String toJson(object) {
    if (object == null) {
        "null"
    } else if (object instanceof Collection ||
            object.class.isArray() ||
            object instanceof Iterator ||
            object instanceof Enumeration) {
        "[" + object.collect { toJson(it) }.join(',') + "]"
    } else if (object instanceof Enum) {
        '"' + object.name() + '"'
    } else {
        def properties = object.properties
        properties.remove('class')
        properties.remove('declaringClass')
        properties.remove('metaClass')
        toJson(properties)
    }
}

コードがオブジェクトのプロパティメンバーを呼び出してオブジェクトメンバーを返すことがわかるように、フィールドの順序は宣言の順序ではなく、JVMに依存します。

順序を維持したい場合は、オブジェクトを表すマップを渡すか、JSONオブジェクトを手動で順番に作成する必要があります。

もう1つの方法は、独自のカスタムビルダーを作成することです。これは、はるかに複雑です...

于 2012-06-10T22:55:52.047 に答える