如何为JAXB设置浮点格式(json使用eclipse moxy)

时间:2016-12-07 23:12:41

标签: java json jaxb moxy

我有一个简单的pojo类:

@XmlRootElement
public static class MyClass {
  private double f; //[0-1]

  @XmlAttribute
  //@XmlJavaTypeAdapter(FixedFloatingPointXmlAdapter.class) <-- has issues
  public double getF() {
    return f;
  }
}

字段f保存范围[0,1]中的值,有时可能很小。我想避免看到像1.234E-7(科学记谱法)这样的东西,并希望设置用于打印字段f的格式。

我已经看到其他建议使用XmlAdapter的答案,如下所示:

public class FixedFloatingPointXmlAdapter extends XmlAdapter<String, Double> {
  private static final DecimalFormat FORMAT = new DecimalFormat("0.00000000");

  @Override
  public Double unmarshal(String v) throws Exception {
    return v == null ? null : Double.parseDouble(v);
  }

  @Override
  public String marshal(Double v) throws Exception {
    return v == null ? null : FORMAT.format(v);
  }
}

但问题是该值将打印为json STRING (所以"0.25000000"而不是0.25000000) - 因为XmlAdapter返回一个String(不是因为FORMAT放置引号。它不是)

是否有任何JAXB / moxy注释允许我控制格式而不将字段转换为json字符串?

1 个答案:

答案 0 :(得分:2)

此解决方案正在使用EclipseLink MOXy的{​​{3}}。

import org.eclipse.persistence.oxm.annotations.XmlTransformation;
import org.eclipse.persistence.oxm.annotations.XmlWriteTransformer;

@XmlRootElement
public static class MyClass {
  @XmlAttribute
  @XmlReadTransformer(transformerClass=FixedFloatingTransformer.class)
  @XmlWriteTransformer(xmlPath="@f", transformerClass=FixedFloatingTransformer.class)
  private double f; //[0-1]

  public double getF() {
    return f;
  }
}

以下是transformerClass的实现。

import java.text.DecimalFormat;

import org.eclipse.persistence.mappings.foundation.AbstractTransformationMapping;
import org.eclipse.persistence.mappings.transformers.AttributeTransformer;
import org.eclipse.persistence.mappings.transformers.FieldTransformer;
import org.eclipse.persistence.sessions.Record;
import org.eclipse.persistence.sessions.Session;

public class FixedFloatingTransformer implements FieldTransformer, AttributeTransformer { 
  private AbstractTransformationMapping mapping;
  private static DecimalFormat FORMAT = new DecimalFormat("0.00000000");

  public Object buildAttributeValue(Record r, Object obj, Session arg2) {
    return r.get(mapping.getFields().get(0));
  }

  public Object buildFieldValue(Object instance, String xpath, Session session) {
    Object o2 = mapping.getAttributeValueFromObject(instance);
    if (o2 instanceof Number) {
      return ((DecimalFormat)FORMAT.clone()).format((Number)o2);
    }
    return null;
  }

  public void initialize(AbstractTransformationMapping mapping) {
    this.mapping = mapping;
  }
}

2016/12/13更新

@XmlSchemaType将对象解组为JSON字符串时,会引用moxy。 如果namebooleannumber typemoxy将输出没有带引号的字符串的值字符串。

  

示例1:您必须将格式化值设置为f

public static class MyClass {
  private String f;

  @XmlAttribute
  @XmlSchemaType(name="double")
  public String getF() {
    return f;
  }
}
  

示例2:添加额外的getter以返回格式化值。

public static class MyClass {
  private double f;

  @XmlTransient //preventing the mapping
  public double getF() {
    return f;
  }

  @XmlAttribute(name="f")
  @XmlSchemaType(name="double")
  public String getFAsString() {
    return new DecimalFormat("0.00000000").format(f);
  }
}