1

同様の質問がここにあり、答えが示唆するように、実際にコンバーターを使用しようとしました。

XML の 10 進数値のフォーマット

オブジェクトを xml と json の両方にシリアル化しています。必要に応じて、XStream と JsonHierarchicalStreamDriver を使用しています。

オブジェクトには double 型のプロパティがあります。これらは正常にシリアル化されていました。xml では、次のようにシリアル化されます。

<value>3.14159265</value>

json では次のようになりました。

value: 3.14159265

値を指定された小数点以下の桁数に丸める必要があります。

最初の試みで、すべての double を小数点以下 2 桁に丸める Converter を作成しました。これは上記のようにレンダリングされます (値が丸められることを除いて) が、問題は、さまざまなプロパティをさまざまな有効数字に丸める必要があり、コンバーターは「マーシャル」メソッドのときに小数点以下の桁数を認識できないことです。

2 回目の試行では、カスタム オブジェクトを使用して、double オブジェクトと小数点以下の桁数を保持する double を置き換えます。別のコンバーターが必要です。これは xml ではうまく機能しますが、json では、値を数値としてではなく文字列 (引用符で囲んだもの) としてレンダリングします (これは私が本当に望んでいるものです)。

丸められた double を数値としてレンダリングするにはどうすればよいですか?

ありがとう

4

1 に答える 1

0

興味のある方は、JsonHierarchicalStreamDriver は JsonWriter というクラスを使っているようです。それらの間で、Double、Integer などはすべて JSON 数値に変換されるものと見なされますが、カスタム オブジェクトはテキストとして変換されます (つまり、引用符で囲まれます)。とにかく、値をレンダリングする方法を指定する方法はないようです。

それでも行う必要がある場合は、いくつかのオプションがあります。JsonHierarchicalStreamDriver に代わるものを使用できる場合があります。ドキュメントは、JettisonMappedXmlDriver のバージョンが文字列のようなすべての数値を JSON 数値に変換することを暗示しています (常に望ましいとは限りません)。

私は次の汚いハックに行きました:

引用符を削除できる新しいライターを作成します。

public static class HackJsonWriter extends JsonWriter {
    public HackJsonWriter(Writer writer) {
        super(writer);
    }

    private boolean dropQuotes = false;

    public void dropQuotes() {
        dropQuotes = true;
    }

    public void allowQuotes() {
        dropQuotes = false;
    }

    @Override
    protected void addValue(String value, AbstractJsonWriter.Type type)
    {
        if (dropQuotes) {
            super.addValue(value, AbstractJsonWriter.Type.NULL);
        }
        else {
            super.addValue(value, type);
        }
    }
}

次の方法でライターの作成を上書きします。

new XStream(new JsonHierarchicalStreamDriver() {
    @Override
    public HierarchicalStreamWriter createWriter(Writer writer) {
        return new HackJsonWriter(writer);
    }
});

ハッキングを見つけて処理するコンバーターを作成します。

public static class HackRoundedDoubleConverter implements Converter {

    private HackRoundedDoubleConverter() {
    }

    @Override
    public boolean canConvert(Class clazz) {
        return RoundedDouble.class.isAssignableFrom(clazz);
    }

    @Override
    public void marshal(Object value, HierarchicalStreamWriter writer, MarshallingContext context) {
        if (value == null) {
            return; // now that i think about it, this should probably write "null" (no quotes), but I was handling that elsewhere
        }
        RoundedDouble number = (RoundedDouble)value;
        if (Double.isNaN(number.getValue()) || Double.isInfinite(number.getValue())) {
            return; // at this point, we would have a problem.  an empty node will be created no matter what (and it translates to an empty object in javascript).
        }

        if (writer.underlyingWriter() instanceof HackJsonWriter) {
            HackJsonWriter hackWriter = (HackJsonWriter)writer.underlyingWriter();
            hackWriter.dropQuotes();
            writer.setValue(number.getRoundedValue());
            hackWriter.allowQuotes();
        }
        else {
            writer.setValue(number.getRoundedValue());
        }
    }

    @Override
    public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
        // only interested in the one direction
        return null;
    }
}

コンバーターを登録します。

    xstream.registerConverter(new HackRoundedDoubleConverter());

RoundedDouble は、double 値と小数点以下の桁数という 2 つのプロパティを持つクラスです。

私が言うように、これはハックであり (非常に壊れやすく、私が気付いていない多くの問題を抱えている可能性があります)、その方法を考え出すときにおそらく法律を破りました。私はおそらくそれを使用することさえありませんが、それは私の元の質問に答えます.

于 2012-06-01T09:34:35.943 に答える