1. ホーム
  2. json

ジャクソン・ジャクソン・コア

2022-02-26 03:20:26
<パス

元記事へのリンク: http://www.dubby.cn/detail.html?id=9069

ここでは、jackson-core が提供する JsonParser JsonGenerator を使用して、基本的なシリアライズとデシリアライズを実装しています。

1. データクラスとエンティティクラス

まず、JSON文字列の定義から始めます。

{
  "id":123456789,
  "text":"I'm Yang Zheng, I'm at http://www.dubby.cn",
  "fromUserId":123456, 
  "toUserId":789,
  "languageCode":"zh"
}

パースするときにデータを運ぶPOJOを与えます。

public class TwitterEntry {
    long _id;
    String _text;
    int _fromUserId, _toUserId;
    String _languageCode;

    public TwitterEntry() {
    }

    public void setId(long id) {
        _id = id;
    }

    public void setText(String text) {
        _text = text;
    }

    public void setFromUserId(int id) {
        _fromUserId = id;
    }

    public void setToUserId(int id) {
        _toUserId = id;
    }

    public void setLanguageCode(String languageCode) {
        _languageCode = languageCode;
    }

    public long getId() {
        return _id;
    }

    public String getText() {
        return _text;
    }

    public int getFromUserId() {
        return _fromUserId;
    }

    public int getToUserId() {
        return _toUserId;
    }

    public String getLanguageCode() {
        return _languageCode;
    }

    public String toString() {
        return "[Tweet, id: " + _id + ", text: " + _text + "', from: " + _fromUserId + ", to: " + _toUserId + ", lang: & quot; + _languageCode + "]";
    }
}

2. デシリアライジング アンマーシャル (JSON->POJO)

private static TwitterEntry read(JsonParser jp) throws IOException {
        // Check if it's JSON
        if (jp.nextToken() ! = JsonToken.START_OBJECT) {
            throw new IOException("Expected data to start with an Object");
        }
        TwitterEntry result = new TwitterEntry();
        // Iterate through the properties and assign values one by one
        while (jp.nextToken() ! = JsonToken.END_OBJECT) {
            String fieldName = jp.getCurrentName();
            jp.nextToken();
            switch (fieldName) {
                case "id":
                    result.setId(jp.getLongValue());
                    break;
                case "text":
                    result.setText(jp.getText());
                    break;
                case "fromUserId":
                    result.setFromUserId(jp.getIntValue());
                    break;
                case "toUserId":
                    result.setToUserId(jp.getIntValue());
                    break;
                case "languageCode":
                    result.setLanguageCode(jp.getText());
                    break;
                default:
                    throw new IOException("Unrecognized field '" + fieldName + "'");
            }
        }
        //close the parser
        jp.close();
        return result;
    }

呼び出す場所は以下の通りです。

JsonFactory jsonF = new JsonFactory();

        String jsonStr = "{\n" +
                " \n"id\":123456789,\n" + 
                " \"text\":\"I'm Yang Zheng, I'm at http://www.dubby.cn\",\n" +
                " \"fromUserId\":123456, \n" +
                " \"toUserId\":789,\n" +
                " \"languageCode\":\"zh\"\n" +
                "}";
        System.out.println(jsonStr);

        JsonParser jp = jsonF.createParser(jsonStr);
        TwitterEntry entry = read(jp);
        System.out.println(entry.toString());

3. シリアライジング マーシャリング(POJO -> JSON)

private static void write(JsonGenerator jg, TwitterEntry entry) throws IOException {
        jg.writeStartObject();
        jg.writeNumberField("id", entry.getId());
        jg.writeStringField("text", entry.getText());
        jg.writeNumberField("fromUserId", entry.getFromUserId());
        jg.writeNumberField("toUserId", entry.getToUserId());
        jg.writeStringField("langugeCode", entry.getLanguageCode());
        jg.writeEndObject();
        jg.close();
    }


は次のように呼び出されます。

ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        JsonGenerator jg = jsonF.createGenerator(byteArrayOutputStream, JsonEncoding.UTF8);
        jg.useDefaultPrettyPrinter();
        write(jg, entry);
        System.out.println(byteArrayOutputStream.toString());

4. その他のオプション

4.1 JsonFactory のオプション(ネーミングの正規化)

属性名のみ

JsonFactory f = new JsonFactory();
f.disable(JsonFactory.FEATURE.CANONICALIZE_FIELD_NAMES);

<テーブル オプション名 デフォルト値 意味 フィールド名を正規化する 真 は、入力 (バイトまたは文字ストリーム) から名前の文字列がデコードされると、 シンボルテーブルに追加され、次に同じ名前を見たときに (同じファクトリで構築されたパーサーが) デコードする際のオーバーヘッドを軽減することを意味します。 インターンフィールド名 真 1. 正規化が有効な場合、この機能はデコードされる文字列が String.internal() を使用するかどうかを決定します - これは多くの場合、デシリアライズのパフォーマンスを向上させることができます。これは、同一性比較を使用できるため、デシリアライズのパフォーマンスをさらに向上させることができます。2. 文字列が繰り返されない場合、あるいは異なる文字列の数が多すぎる場合(数千)、このオプションをオフにすることを検討するとよいでしょう。そうしないと、メモリを大量に消費することになります。 FAIL_ON_SYMBOL_HASH_OVERFLOW (2.4 でサポート) 真 正規化では、バイト/文字列を名前に解析するためにハッシュベースのアプローチを使用するため、理論的には、非常に高い競合率を持つ名前のセットを構築することが可能である。このような場合、ハッシュ検索のパフォーマンスが著しく低下する可能性があります。この可能性を防ぐため、シンボルテーブルでは、異常に高い衝突数に基づいて攻撃の可能性を検出するヒューリスティックを使用している。 USE_THREAD_LOCAL_FOR_BUFFER_RECYCLING (2.6 でサポートされました) 真 コンテンツの読み書きのために char [] や byte [] バッファを確保することは、特に比較的小さなドキュメントを扱う場合に大きな影響を与えるので、デフォルトでは JsonFactory は SoftReference の ThreadLocal を使って BufferRecycler を参照します:これにより複数の読み書きを行うことができるのです。通常、このオプションはパフォーマンスを向上させるためにオンにしますが、Android プラットフォームでは SoftReferences の処理は二の次で、役に立たないリサイクル、あるいはオーバーヘッドを追加するだけなので、オフにすることを検討してもよいでしょう。しかし、オフにする前に、(a) 自分が何をしているかを知っていること、(b) 測定可能なパフォーマンス向上が得られることを確認してください。

4.2 JsonGeneratorのオプション

JsonFactory f = new JsonFactory();
f.enable(JsonGenerator.Feature.ESCAPE_NON_ASCII);
f.disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET). f.disable(JsonGenerator;
JsonGenerator g = f.createGenerator(destination);
g.enable(JsonGenerator.Feature.STRICT_DUPLICATE_DETECTION);

<テーブル オプション名 デフォルト値 意味 auto_close_target 真 generator.close()が呼ばれたとき、ターゲットリソース(OutputStream、Writer)が自動的に閉じられるかどうかを決定します(リソースがジェネレータによって作成されていない場合でも同様です)。 flush_passed_to_stream 真 JsonGenerator.flush() の呼び出しが、ベースターゲット上で flush() も呼び出すかどうかを決定します; 無効の場合、 flush() はフラッシュされていないコンテンツのみを書き込みます; 有効の場合、 flush() も呼び出されます。 auto_close_json_content。 真 quote_field_names。 真 引用:非数値的な数字 真 文字列としての数字 虚偽 WRITE_BIGDECIMAL_AS_PLAIN (2.3対応) 虚偽 エスケープノンアスキー 虚偽 STRICT_DUPLICATE_DETECTION (2.3対応) 虚偽 IGNORE_UNKNOWN (2.5対応) 虚偽

4.3 JsonParserのオプション

JsonFactory f = new JsonFactory();
f.enable(JsonParser.Feature.ALLOW_COMMENTS);
f.disable(JsonParser.FEATURE.ALLOW_SINGLE_QUOTES);
JsonParser p = f.createParser(jsonSource);
p.enable(JsonParser.FEATURE.STRICT_DUPLICATE_DETECTION);

<テーブル オプション名 デフォルト値 意味 auto_close_source 真 ALLOW_COMMENTS 虚偽 JSONの場合 \\\ \**\ スタイルコメント allow_yaml_comments false allow_unquoted_field_names を指定します。 虚偽 シングルクォートを許可する 虚偽 allow_unquoted_control_chars 虚偽 バックスラッシュのエスケープを許可する任意の文字 虚偽 許可する数値の範囲 虚偽 数字以外を許可する 虚偽 ALLOW_MISSING_VALUES (2.8対応) 虚偽 STRICT_DUPLICATE_DETECTION (2.3対応) 虚偽 IGNORE_UNDEFINED2.6対応 虚偽

ここに例を示します。

JsonFactory jsonF = new JsonFactory();

        String jsonStr = "{\n" +
                " \"id\":123456789,\n" + "//comment1\n" + "/*comment1*/\n" +
                " \"text\":\"I'm Yang Zheng, I'm at http://www.dubby.cn\",\n" +
                " \"fromUserId\":123456, \n" +
                " \"toUserId\":789,\n" +
                " \"languageCode\":\"zh\"\n" +
                "}";
        System.out.println(jsonStr);

        JsonParser jp = jsonF.createParser(jsonStr);
        // purposely add some comments to the above JSON string, if you don't enable allow comments here, it will report an error
        jp.enable(JsonParser.Feature.ALLOW_COMMENTS);
        TwitterEntry entry = read(jp);
        System.out.println(entry.toString());


結果

{
  "id":123456789,
//注释1
/*注释1*/
  "text":"我是杨正,我在http://www.dubby.cn",
  "fromUserId":123456, 
  "toUserId":789,
  "languageCode":"zh"
}
[Tweet, id: 123456789, text: 我是杨正,我在http://www.dubby.cn', from: 123456, to: 789, lang: zh]