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

How to set floating point format for JAXB (json using eclipse moxy)

我有一个简单的 pojo class:

@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 returns 一个字符串(不是因为 FORMAT 放置了引号。它没有)

是否有任何 JAXB/moxy 注释可以让我在不将字段转换为 json 字符串的情况下控制格式?

此解决方案正在使用 EclipseLink MOXy 中的 transformation annotations

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更新

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

Sample 1: You have to set formated value to f.

public static class MyClass {
  private String f;

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

Sample 2 : Add extra getter to return formatted value.

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);
  }
}