序列化一个 javax.measure.Quantity 属性

Serialize a javax.measure.Quantity property

如果我尝试将对象序列化为 JSON 并将其发送到 RESTful Web 服务,数量 属性 != null,我会收到以下错误

Caused by: java.lang.RuntimeException: com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (WhosebugError) (through reference chain: java.util.ArrayList[0]->tec.units.ri.Identity["conversionSteps"]->java.util.ArrayList[0]->tec.units.ri.Identity["conversionSteps"]-> ... (and so on))
    at org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient4Engine.loadHttpMethod(ApacheHttpClient4Engine.java:430)
    at org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient4Engine.invoke(ApacheHttpClient4Engine.java:281)
Caused by: com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (WhosebugError) (through reference chain: java.util.ArrayList[0]->tec.units.ri.Identity["conversionSteps"]->java.util.ArrayList[0]->tec.units.ri.Identity["conversionSteps"]->java.util.ArrayList[0]->tec.units.ri.Identity["conversionSteps"]-> ... (and so on))
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:694)
    at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:157)
    at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serializeContents(IndexedListSerializer.java:119)
    at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serialize(IndexedListSerializer.java:79)
    at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serialize(IndexedListSerializer.java:18)
    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:672)
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:678)
    at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:157)
    at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serializeContents(IndexedListSerializer.java:119)
    at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serialize(IndexedListSerializer.java:79)
    at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serialize(IndexedListSerializer.java:18)
    ...
(and so on)

这是简化的实体...

import javax.measure.Quantity;
import javax.measure.quantity.Mass;

public class Compound {

    private Quantity<Mass> regAmount;

    public Quantity<Mass> getRegAmount() {
        return regAmount;
    }

    public void setRegAmount(Quantity<Mass> regAmount) {
        this.regAmount = regAmount;
    }
}

这是我如何设置值的示例:

Compound compound = new Compound();
double value = 1;
Unit<Mass> unit = Units.KILOGRAM;
Quantity<Mass> quantity = Quantities.getQuantity(value, unit);
compound.setRegAmount(quantity);

这是抛出错误的地方(适用于所有其他 20 个没有数量的实体):

Builder builder = ClientBuilder.newClient()
    .target(webServiceUrl)
    .path(path)
    .request(MediaType.APPLICATION_JSON);

Entity<E> e = Entity.json(entity); // works
response = builder.put(e); // error if regAmount != null

使用的技术:Jackson, RestEasy, javax.measure.unit-api (ver. 1.0), tec.units.unit-ri (ver. 1.0.3)

问题:

  1. 你知道问题是什么以及如何解决这个问题吗?
  2. 是否有不同的方式来设置 regAmount?
  3. 您能推荐不同的方法或技术吗?

非常感谢!

JSR 363 与 Jackson 配合得很好,从 Opower(现为 Oracle)贡献的这个模块中可以看出 https://github.com/unitsofmeasurement/jackson-module-unitsofmeasure

它不使用 RI,虽然堆栈跟踪不是很透明,但可能的原因是,与 Java SE 端口 uom-se 不同的 RI 不使用 Serializable.因为 RI 与 Java ME 8 Embedded 兼容并且不包含 Serializable。请尝试 uom-se,如果它解决了问题,请告诉我们。

我尝试了一些其他的接口实现,但没有成功。

我找到了一个足以满足 RESTful Web 服务目的的解决方案。因此,我使用了一个自定义序列化程序,它为我提供了数量的值和单位,这实际上是我在客户端重建数量所需的一切。

public class QuantitySerializer<Q extends Quantity<Q>> extends JsonSerializer<Quantity<Q>> {

    @Override
    public void serialize(Quantity<Q> value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        gen.writeStartObject();
        try {
           gen.writeNumberField("value", value.getValue().intValue());
           gen.writeStringField("unit", value.getUnit().toString());
        } catch (NullPointerException e) {}
        gen.writeEndObject();
    }
}