类似的问题在这里,我确实试图使用转换器,正如答案所示。
Formatting decimal values for XML
我将对象序列化为xml和json。我在需要时使用XStream和JsonHierarchicalStreamDriver。
对象具有double类型的属性。这些序列化很好。在xml中,它被序列化为:
<value>3.14159265</value>
在json中,它是:
value: 3.14159265
我现在要求将值四舍五入到给定的小数位数。
在我的第一次尝试中,我写了一个转换器,它将所有双打四舍五入到小数点后两位。这是如上所示(除了值被舍入),但问题是不同的属性需要舍入到不同的有效数字,并且转换器不知道在“marshal”方法时有多少小数位。
我的第二次尝试使用自定义对象替换double,它保存double对象和小数位数。另一个转换器是必需的,这适用于xml,但在json中它将值呈现为字符串(即引号)而不是数字(这是我真正想要的)。
如何将圆角双精度渲染为数字?
由于
答案 0 :(得分:0)
如果有人感兴趣,似乎JsonHierarchicalStreamDriver使用了一个名为JsonWriter的类。在它们之间,它们假设任何双打,整数等转换为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值和一些小数位。
正如我所说,它是一个黑客(它非常脆弱,可能有许多我甚至没有发现的问题),我可能在弄清楚如何做到这一点时违法。我可能甚至不会使用它,但它回答了我原来的问题。