0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

JSON In JavaのJSONObjectのカスタマイズ

Last updated at Posted at 2025-03-23

JSON In Java。パッケージ名が「org.json」

元ソースは
https://github.com/stleary/JSON-java/issues/822#issuecomment-2105977372

変えたところは
OrderedJSONTokenerを内部クラスではなく別クラスしたところだけ。
あとは全く同じ

修正後のメリット

可読性が向上

OrderedJSONObject は JSON の順序を保持する役割 のみに集中

OrderedJSONTokener は JSON のパースを担当

拡張性が向上

OrderedJSONTokener を OrderedJSONObject 以外のクラスでも再利用可能

保守性が向上

修正時に影響範囲が狭くなる

OrderedJSONObject の責務が明確になり、修正しやすい

OrderedJSONObject.java

import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;
import java.lang.reflect.Field;
import java.util.LinkedHashMap;

public class OrderedJSONObject extends JSONObject {

    public OrderedJSONObject() {
        super();
        createOrdered();
    }

    public OrderedJSONObject(String jsonString) {
        this();
        fromString(jsonString);
    }

    public OrderedJSONObject(OrderedJSONTokener tokener) {
        this();
        fromTokener(tokener);
    }

    /**
     * Use reflection to override the underlying data structure
     */
    private void createOrdered() {
        try {
            Field mapField = JSONObject.class.getDeclaredField("map");
            mapField.setAccessible(true);
            mapField.set(this, new LinkedHashMap<>());
        } catch (NoSuchFieldException | IllegalAccessException e) {
            throw new RuntimeException("Unable to preserve JSONObject ordering. Failed to override map.");
        }
    }

    private void fromString(String source) {
        OrderedJSONTokener tokener = new OrderedJSONTokener(source);
        fromTokener(tokener);
    }

    private void fromTokener(OrderedJSONTokener tokener) {
        if (tokener.nextClean() != '{') {
            throw tokener.syntaxError("A JSONObject text must begin with '{'");
        }
        while (true) {
            char c = tokener.nextClean();
            switch (c) {
                case '\u0000':
                    throw tokener.syntaxError("A JSONObject text must end with '}'");
                case '}':
                    return;
                default:
                    tokener.back();
                    String key = tokener.nextValue().toString();
                    c = tokener.nextClean();
                    if (c != ':') {
                        throw tokener.syntaxError("Expected a ':' after a key");
                    }
                    this.putOnce(key, tokener.nextValue());
                    switch (tokener.nextClean()) {
                        case ',':
                        case ';':
                            if (tokener.nextClean() == '}') {
                                return;
                            }
                            tokener.back();
                            break;
                        case '}':
                            return;
                        default:
                            throw tokener.syntaxError("Expected a ',' or '}'");
                    }
            }
        }
    }

    @Override
    public String toString(int indentSpaces) {
        return super.toString(indentSpaces);
    }
}

OrderedJSONTokener.java

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;

public class OrderedJSONTokener extends JSONTokener {

    public OrderedJSONTokener(String s) {
        super(s);
    }

    @Override
    public Object nextValue() throws JSONException {
        char c = this.nextClean();
        switch (c) {
            case '"':
            case '\'':
                return this.nextString(c);
            case '[':
                this.back();
                return new JSONArray(this);
            case '{':
                this.back();
                return new OrderedJSONObject(this);
            default:
                StringBuilder sb = new StringBuilder();
                while (c >= ' ' && ",:]}/\\\"[{;=#".indexOf(c) < 0) {
                    sb.append(c);
                    c = this.next();
                }
                this.back();
                String string = sb.toString().trim();
                if ("".equals(string)) {
                    throw this.syntaxError("Missing value");
                } else {
                    return JSONObject.stringToValue(string);
                }
        }
    }
}

実行例

// Jsonにする型のString型を定義
String jsonStr = """
		{"b":2,"a":1,"c":3} 
		""";
OrderedJSONObject obj2 = new OrderedJSONObject(jsonStr);
System.out.println(obj2.toString()); 

// JSONからXMLに変換
String xml = XML.toString(obj2);
System.out.println(xml);       
{"b":2,"a":1,"c":3}
<b>2</b><a>1</a><c>3</c>
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?