web-dev-qa-db-ja.com

Java:列挙型で構成されるオブジェクトをJsonオブジェクトに変換

ObjectをJson形式に変換するためにorg.jsonライブラリを使用しています。以下のコードスニペットをご確認ください。

public enum JobStatus implements Serializable{
     INCOMPLETE,
     INPROGRESS,
     ABORTED,
     COMPLETED
}

public class Job implements Serializable {
    private string id;
    private JobStatus status;
    ...
}

...

// Create Job Object
Job job = new Job("12345", JobStatus.INPROGRESS);

// Convert and print in JSON format
System.out.println(new JSONObject(job).toString());

次のような出力が表示されます。

 {"id":"12345", "status" : {}}

空白が表示され、カーリーベースが追加されます。どういう意味ですか?誰もこの問題を経験していますか?

16
Ronnie

まず第一に、このライブラリ(org.json)を使用しないことを強くお勧めします。これは非常に古く、サポートされていない(私が知っているように)ライブラリです。 Jackson または Gson をお勧めします。

ただし、JSONObjectが本当に必要な場合は、enumにゲッターを追加できます。

 public enum JobStatus implements Serializable{
    INCOMPLETE,
    INPROGRESS,
    ABORTED,
    COMPLETED;

    public String getStatus() {
        return this.name();
    }
}

シリアル化の結果:

{"id":"12345","status":{"status":"INPROGRESS"}}

私が知っているように、JSONObjectは内部に追加データがない列挙型の正しいシリアル化をサポートしていません。

17
Denys Denysiuk

JSONObjectは列挙型をサポートしていないようです。 Jobクラスを変更して、次のようなゲッターを追加できます。

_public String getStatus() {
    return status.name();
}
_

次に、new JSONObject(job).toString()を呼び出すと、以下が生成されます。

_{"id":"12345","status":"INPROGRESS"}
_
2
Bohemian

私にとって、私はJsonで使用する必要がある列挙型によって実装されるインターフェースを作成しました。このインターフェースは、列挙型に値から適切な列挙型自体を知るように強制し、値を返す必要があります...すべての列挙型.CONSTANTは、任意のタイプの値にマップされます(天気または数値)

したがって、この列挙型をJsonオブジェクトに入れたい場合は、enum.CONSTANTに値を教えてください。この値があれば(Jsonから)、列挙型から適切なenum.CONSTANTを与えるように要求できますこの値にマッピングされます

インターフェイスは次のとおりです(そのままコピーできます)。

/**
 * 
 * this interface is intended for {@code enums} (or similar classes that needs
 * to be identified by a value) who are based on a value for each constant,
 * where it has the utility methods to identify the type ({@code enum} constant)
 * based on the value passed, and can declare it's value in the interface as
 * well
 * 
 * @param <T>
 *            the type of the constants (pass the {@code enum} as a type)
 * @param <V>
 *            the type of the value which identifies this constant
 */
public interface Valueable<T extends Valueable<T, V>, V> {

    /**
     * get the Type based on the passed value
     * 
     * @param value
     *            the value that identifies the Type
     * @return the Type
     */
    T getType(V value);

    /**
     * get the value that identifies this type
     * 
     * @return a value that can be used later in {@link #getType(Object)}
     */
    V getValue();
}

次に、このインターフェイスを実装する小さな列挙型の例を示します。

public enum AreaType implements Valueable<AreaType, Integer> {
    NONE(0),
    AREA(1),
    NEIGHBORHOOD(2);

    private int value;

    AreaType(int value) {
        this.value = value;
    }

    @Override
    public AreaType getType(Integer value) {

        if(value == null){
            // assume this is the default
            return NONE;
        }

        for(AreaType a : values()){
            if(a.value == value){ // or you can use value.equals(a.value)
                return a;
            }
        }
        // assume this is the default
        return NONE;
    }

    @Override
    public Integer getValue() {
        return value;
    }

}

この列挙型をJsonに保存するには:

AreaType areaType = ...;
jsonObject.put(TAG,areaType.getValue());

jsonオブジェクトから値を取得します:

int areaValue = jsonObject.optInt(TAG,-1);
AreaType areaType = AreaType.NONE.getType(areaValue);

たとえば、areaValueが1の場合、AreaTypeは「Area」などになります。

1
ObjectMapper mapper= new ObjectMapper();

new JSONObject(mapper.writeValueAsString(job));

トリックを行います。 EnumsおよびDateTime型は正常に見え、jsonオブジェクトで適切に変換されます。

私は答えを求めている人としてこのページに来ました、そして、私の研究はこの質問に答えるのを助けました。

1
Hari