33

私がpojoを持っているとしましょう:

import org.codehaus.jackson.map.*;

public class MyPojo {
    int id;
    public int getId()
    { return this.id; }

    public void setId(int id)
    { this.id = id; }

    public static void main(String[] args) throws Exception {
        MyPojo mp = new MyPojo();
        mp.setId(4);
        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(SerializationConfig.Feature.WRAP_ROOT_VALUE, true);
        System.out.println(mapper.getSerializationConfig().isEnabled(SerializationConfig.Feature.WRAP_ROOT_VALUE));
        System.out.println(mapper.writeValueAsString(mp));
    }
}

Jackson ObjectMapperを使用してシリアル化すると、次のようになります。

true
{"id":4}

でも私はしたい

true
{"MyPojo":{"id":4}}

私はあちこちを検索しましたが、Jacksonsのドキュメントは実際には整理されておらず、ほとんどが古くなっています。

4

11 に答える 11

39

@JsonTypeInfoクラス レベルでjackson アノテーションを追加すると、期待どおりの出力が得られます。クラスに変更なしを追加しました。

package com.test.jackson;

import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;

import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;

@JsonTypeInfo(include=As.WRAPPER_OBJECT, use=Id.NAME)
public class MyPojo {
    // Remain same as you have
}

出力:

{
    "MyPojo": {
        "id": 4
    }
}
于 2015-07-01T10:23:58.580 に答える
28

私はジャクソンを使用していませんが、検索すると、あなたが望むものと思われるこの構成が見つかりました: WRAP_ROOT_VALUE

アノテーション イントロスペクター (特に @XmlRootElement を使用する JAXB の場合) によって決定されるように、キーが「ルート名」である単一のプロパティ JSON オブジェクト内にラップされたルート値 (通常は JSON オブジェクトですが、任意の型) を作成するために有効にできる機能.name) またはフォールバック (非修飾クラス名)。この機能は主に JAXB との互換性を目的としています。

デフォルト設定は false で、ルート値がラップされないことを意味します。

マッパーを構成できるように:

objectMapper.configure(SerializationConfig.Feature.WRAP_ROOT_VALUE, true);

お役に立てば幸いです...

于 2010-03-12T20:18:54.453 に答える
14

以下はこれを達成する方法です

Map<String, MyPojo> singletonMap = Collections.singletonMap("mypojo", mp);
System.out.println(mapper.writeValueAsString(singletonMap));

出力 { "mypojo" : { "id" : 4}}

ここでの利点は、json オブジェクトのルート キーに on 名を付けることができることです。上記のコードにより、mypojoがルート キーになります。このアプローチは、json オブジェクトの繰り返しに Mustache.js のような Java スクリプト テンプレートを使用する場合に最も役立ちます。

于 2013-06-10T02:38:31.393 に答える
4

これには素晴らしい注釈もあります。

@JsonRootName(value = "my_pojo")
public class MyPojo{
  ...
}

生成されます:

{
  "my_pojo" : {...}
}
于 2016-04-17T07:47:48.870 に答える
1

私が使用した別の方法があり、それは私のために働いた。私はサードパーティのjarを使用しているため、注釈を制御できません。だから私はちょっとしたハックを通して書かなければなりませんでした。

オーバーライド:org.codehaus.jackson.map.ser.BeanSerializerFactory.findBeanProperties(SerializationConfig, BasicBeanDescription)

以下のようにプロパティを追加します

List<BeanPropertyWriter> props = super.findBeanProperties(config, beanDesc);
BeanPropertyWriter bpw = null;
try {
     Class cc = beanDesc.getType().getRawClass();
     Method m = cc.getMethod("getClass", null);
     bpw = new BeanPropertyWriter("$className", null, null, m, null,true, null);
} catch (SecurityException e) {
  // TODO
} catch (NoSuchMethodException e) {
  // TODO
}
props.add(bpw);
return props;

このようにして、私はより多くの制御を取得し、他の種類のフィルターも実行できます。

于 2012-03-19T14:17:54.850 に答える
1

最も簡単な解決策はどうですか。次のようなラッパークラスを使用するだけです:

class Wrapper {
   public MyPojo MyPojo;
}

コードでラップ/ラップ解除しますか?

これを超えて、このような追加の json オブジェクト エントリが必要な理由を知っておくと役立ちますか? これは、xml api を介して json をエミュレートするライブラリによって行われることは知っていますが (xml から json への変換による xml と json 間のインピーダンスのため)、純粋な json ソリューションの場合、通常は必要ありません。

実際のタイプが何であるかを理解できるようにするためですか?もしそうなら、ジャクソンがそれを自動的に処理できるように、ポリモーフィック型情報を有効にすることを検討できますか? (詳細については、 1.5 リリース ノートの PTH のエントリを参照してください)。

于 2010-03-22T16:40:18.890 に答える
0

私はこれに対するOPの解決策を聞くことに興味があります。RESTful WebサービスがクライアントのオブジェクトをXMLまたはJSONとしてシリアル化する場合にも、同様の問題が発生します。Javascriptクライアントは、解析できるようにラッピングタイプを知っている必要があります。タイプをURIパターンに結合することはオプションではありません。

ありがとう。

編集:Spring MappingJacksonJsonMarshallerがマーシャリング時にラッピングクラスを追加することに気づいたので、デバッグでコードをステップスルーし、Springが単一のキーと値のペアでHashMapを渡し、キーがラッピング名で値が物体。そこで、JacksonJaxbJsonProviderを拡張し、writeTo()メソッドをオーバーライドして、以下を追加しました。

HashMap<String, Object> map = new HashMap<String, Object>();
map.put(value.getClass().getSimpleName(), value);
super.writeTo(map, type, genericType, annotations, mediaType, httpHeaders,entityStream);

ちょっとしたハックですが、うまく機能します。

于 2010-04-30T15:30:49.270 に答える
0

すべての JSON にバックエンド タイプ (文字列として) とフロント エンドでレンダリングするために使用されるコンポーネント タイプ (Angular や Vue などを使用する場合) の両方を含めることをお勧めします。

これを行う理由は、単一のコード セットでさまざまな型を処理できるようにするためです。

たとえば vue では、データに UI コンポーネントの名前を含めると、特に、親テンプレートの単一のタグのみを使用して、さまざまなタイプの子のリストを画面にレンダリングすることができます。

  <component :is="child.componentType"/>.

バックエンド システムと Web サービスの場合、受信ペイロードに基づいて適切なプロセッサ クラスを検索することで、すべての Web サービスのログ記録、監査、および例外処理を提供する単一の Web サービス プロセッサ クラスを使用することを好みます。これにより、すべての Web サービスの実装がまったく同じ (約 3 行のコード) になり、サービスごとのコードを記述することなく、呼び出しのライフサイクルを通じて詳細なイベント ログを取得できます。

JSON をラップする型を持つことで、それは自己文書化されます。プロパティしか表示されない場合は、対応するエンドポイントが見つかるまで、何を見ているのかわかりません。

データ駆動型ソフトウェアを作成する場合、何を処理しているかを識別できることが基本的な要件です。

于 2018-08-13T21:13:21.127 に答える
0
@JsonTypeInfo(include=As.WRAPPER_OBJECT, use=Id.NAME) 

Arun Prakash が示唆しているように、この注釈は完全に機能します。私はこの形式でjsonを取得しようとしていました:

{"Rowset":{"ROW":{"receiptno":"881604199388936","status":"SUCCESS"}}}

しかし、このようになります:

{"ROW":{"receiptno":"881604199388936","status":"SUCCESS"}}

その注釈が私の問題を解決しました。

于 2016-06-16T04:13:45.230 に答える