JSON Serializer for Units
Is your feature request related to a problem? Please describe. As of now, it is possible to serialize IQuantities with JSON. However, sometimes there is a need to serialize a unit by itself without a value. I.e. in the case when you just want to save a setting that happens to be a unit type. Or in our case we would like to define a multi dimensional table of data and set the unit just once next to it, for readability purposes.
Describe the solution you'd like
A converter for Unit Enums. Or alternatively it would be enough to make
private Enum GetUnit(string unit)
in UnitsNetBaseJsonConverter protected, so that we can implement a converter by ourself.
Describe alternatives you've considered We are currently using an IQuantity with arbritary values, just to save and extract the units. Kind of ugly, kind of confusing for people not familiar with this topic.
I guess, you could just create your own JsonConverter<Enum> inspired by UnitsNetBaseJsonConverter?
If you are interested in attempting a pull request, then we could add this converter to the library for others to benefit from.
Sorry for the late reply by the way, it got lost in the inbox.
I have some of the UnitsNet.Units enums in my setting classes like this example
public PressureUnit SensorUnit { get; set;} = PressureUnit.Bar;
add the Newtonsoft.Json.Converters.StringEnumConverter to my JsonSerializerSettings.Converters witch gives a nice
{
"SensorUnit": "Bar"
}
hope that helps
@vKaras1337 that is a very nice solution, thanks for sharing.
However, you already know the physical unit you want to use. In that case "PressureUnit". In my case I don't know the unit beforehand, because my code reads in generic "tables". The entries of said table may be of any desired unit, be it Mass, Time or Pressure since it is a generic library to be used on top of UnitsNet.
And while Newtonsoft.Json.Converters.StringEnumConverter can serialize
Enum Unit = PressureUnit.Bar;
to
"Unit": "Bar"
it is unable to deserialize it again.
I did not have the time yet to revisit this topic properly as of now. Thanks for your suggestion though, I think this is helpful for a lot of people.
@TimLCondor Oh that is really something..
I was a little curious how I would solve this. Maybe you can use something of it. (thats only a quick test, that converter would need some more to it, error handling, type checks, etc.)
var data = Newtonsoft.Json.JsonConvert.SerializeObject(new MyTestClass(), Newtonsoft.Json.Formatting.Indented).Dump();
Newtonsoft.Json.JsonConvert.DeserializeObject<MyTestClass>(data).Dump();
public class MyTestClass
{
[JsonConverter(typeof(StringEnumConverter))]
public PressureUnit UnitDirect { get; set; } = PressureUnit.Bar;
[JsonConverter(typeof(UnitsNetEnumUnitConverter))]
public Enum UnitGeneric { get; set; } = AreaUnit.SquareKilometer;
}
public class UnitsNetEnumUnitConverter : Newtonsoft.Json.JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType.IsEnum;
}
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
{
return null;
}
if (reader.TokenType == JsonToken.String)
{
var splitValue = reader.Value!.ToString()!.Split('.');
string typeName = splitValue[0];
string enumName = splitValue[1];
return Enum.Parse(Type.GetType($"UnitsNet.Units.{typeName}, UnitsNet")!, enumName);
}
throw new NotSupportedException();
}
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
{
writer.WriteValue($"{value!.GetType().Name}.{Enum.GetName(value.GetType(), value)}");
}
}
witch gives a
{
"UnitDirect": "Bar",
"UnitGeneric": "AreaUnit.SquareKilometer"
}
This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 7 days.
This issue was automatically closed due to inactivity.