Java 使用XStream和JSONHierarchycalStreamDriver来输出值,如何对double进行舍入?
这里有一个类似的问题,正如答案所示,我确实尝试过使用转换器 我正在将对象序列化为xml和json。我在需要时使用XStream和JSONHierarchycalStreamDriver 对象的属性类型为double。这些都很好。在xml中,它序列化为:Java 使用XStream和JSONHierarchycalStreamDriver来输出值,如何对double进行舍入?,java,xml,json,xstream,Java,Xml,Json,Xstream,这里有一个类似的问题,正如答案所示,我确实尝试过使用转换器 我正在将对象序列化为xml和json。我在需要时使用XStream和JSONHierarchycalStreamDriver 对象的属性类型为double。这些都很好。在xml中,它序列化为: <value>3.14159265</value> 我现在需要将值四舍五入到给定的小数位数 在我的第一次尝试中,我编写了一个转换器,它将所有的双精度舍入到小数点后2位。这是如上所述呈现的(值被舍入除外),但问题是不同的
<value>3.14159265</value>
我现在需要将值四舍五入到给定的小数位数
在我的第一次尝试中,我编写了一个转换器,它将所有的双精度舍入到小数点后2位。这是如上所述呈现的(值被舍入除外),但问题是不同的属性需要舍入到不同的有效数字,并且转换器不知道在“marshal”方法中有多少位小数
我的第二次尝试使用自定义对象替换double,它保存double对象和小数位数。需要另一个转换器,这对xml很有效,但在json中,它将值呈现为字符串(即引号),而不是数字(这是我真正想要的)
如何将四舍五入的双精度体渲染为数字
谢谢如果有人感兴趣,那么JsonHierarchicalStreamDriver似乎使用了一个名为JsonWriter的类。在它们之间,它们假设任何双精度、整数等转换为JSON数字,而自定义对象将转换为文本(即用引号括起来)。似乎无论如何都没有指定要如何呈现值 如果您仍然需要完成,有几个选项。您可能可以使用JSONHierarchycalStreamDriver的替代方案。该文档表明,一个版本的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是一个具有两个属性、一个双精度值和小数位数的类
正如我所说,这是一个黑客(它非常脆弱,可能有许多我甚至没有发现的问题),我可能在研究如何做到这一点时违反了法律。我甚至可能不会使用它,但它回答了我原来的问题。快速查看xstream转换器教程可以看到以下示例:“@XStreamConverter(value=BooleanConverter.class,booleans={false},strings={“yes”,“no”})”。因此,您似乎可以为转换器提供一些额外的参数。你能用这些吗?@DenisTulskiy谢谢,但每个实例的小数位数可能不同。如果有一种方法可以将当前对象或当前的“小数位数”传递给转换器,这将解决我的问题……我认为这项任务远远超出了任何编组库的功能。
xstream.registerConverter(new HackRoundedDoubleConverter());