Closed lucasvc closed 2 years ago
You're correct and I don't think you did something wrong.
This Jackson library was ported from the now archived https://github.com/unitsofmeasurement/jackson-module-unitsofmeasure created by Opower before Oracle took it over. There are serializers and deserializers for Unit
and Dimension
, but so far they did not need or add one for a Quantity
. The functionality was pretty much as-is, but if you'd like to contribute to enhancements, you are more than welcome.
Thanks for your reply @keilw. I've been on holidays, but I see you took it over :) Thanks²
I didn't start working on it, so help or PRs are appreciated if you or someone else had time to help. The existing functionality is pretty identical to what was donated by the ex Opower developer, they did not seem to have a use for quantity serialization, thus it did not exist so far. I also started working on a Jakarta JSON-B variant using Jakarta JSON standards, but that is also work in progress: https://github.com/unitsofmeasurement/uom-lib/tree/master/yasson
Oh sorry, I could not review all the commits and I assumed 😅 Then I will try to do some work on it.
I've started looking into this. The main issue is with ProductUnit
s (eg. Units#CUBIC_METRE
).
The value that is used for serialization and deserialization must be the same.
For example, if we take a naive approach to serialize Units#CUBIC_METRE
using SimpleUnitFormat#format(Unit)
, it returns m³
. But if we then try to deserialize it using SimpleUnitFormat#parse(String)
, it will fail, because it expects m^3
.
To work around this, to serialize/deserialize Unit
s, UnitJacksonModule uses UCUMFormat
instead of SimpleUnitFormat
, which serializes/deserializes Units#CUBIC_METRE
as m3
.
Unfortunately, for Quantity
, SimpleQuantityFormat
uses SimpleUnitFormat
internally, and there is no UCUM equivalent for it. The most obvious solution now would be to create an AbstractQuantityFormat
that uses UCUMFormat
internally instead of SimpleUnitFormat
(eg. UCUMQuantityFormat
), or to manually parse the String to separate the numeric value from the unit.
Bump to this! A hard blocker on the project I am working on, need any help?
I hacked this together. However, this is unlikely a proper solution.
import java.io.IOException;
import java.math.BigDecimal;
import javax.measure.Quantity;
import javax.measure.Quantity.Scale;
import javax.measure.Unit;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import tech.units.indriya.quantity.Quantities;
@SuppressWarnings("rawtypes")
public class QuantityJsonDeserializer extends StdDeserializer<Quantity> {
public QuantityJsonDeserializer() {
super(Quantity.class);
}
@Override
public Quantity deserialize(JsonParser jp, DeserializationContext deserializationContext)
throws IOException, JsonProcessingException {
JsonToken currentToken = null;
BigDecimal value = null;
Unit<?> unit = null;
Scale scale = null;
while ((currentToken = jp.nextValue()) != null) {
switch (currentToken) {
case VALUE_NUMBER_FLOAT:
case VALUE_NUMBER_INT:
switch (jp.getCurrentName()) {
case "value":
value = jp.getDecimalValue();
break;
default:
break;
}
break;
case VALUE_STRING:
switch (jp.getCurrentName()) {
case "unit":
unit = jp.readValueAs(Unit.class);
break;
case "scale":
scale = Scale.valueOf(jp.getText());
break;
default:
break;
}
default:
break;
}
}
return Quantities.getQuantity(value, unit, scale);
}
}
Regardless of the maturiy, would you be able to turn that into a PR @bantu? Unlike the core JSR modules this one is free to contribute (as long as you abide to BSD license) without JCP membership, so any PR is welcome.
I was in the midst of making my own deserializer, and this is along the lines of what I was attempting to come up with. I actually have a fork going that has a few other organization changes as well. I don't mind as long as I can deserialize Quantity
, but thought I would mention! I can also wait for the simpler fix to get in, I can't test this anyways due to the other PR I posted on using Java 11
Only thing I might add is error checking, to ensure all three items are actually found and appropriately deserialized before handing them to Quantities.getQuantity()
Regardless of the maturiy, would you be able to turn that into a PR @bantu? Unlike the core JSR modules this one is free to contribute (as long as you abide to BSD license) without JCP membership, so any PR is welcome.
PR opened: #72
Only thing I might add is error checking, to ensure all three items are actually found and appropriately deserialized before handing them to
Quantities.getQuantity()
Feel free to add that to the PR.
I have recently discovered and started to use all the Units of Measurement library echosystem. Now I wanted to serialize/deserialize some
Quantity
's instances, but I have realised that is not possible to deserialize them.The following JUnit 5 (with pojo class included)
throws the exception,