Created
March 17, 2025 12:09
-
-
Save chrisbewz/ca49427d113deb84ea8e881a32ee68e7 to your computer and use it in GitHub Desktop.
System.Text.Json UnitsNet Custom Quantity Converter Sample
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| public sealed class ElectricPotentialConverter : QuantityConverter<ElectricPotential, ElectricPotentialUnit> | |
| { | |
| protected override ElectricPotential FromValueAndUnit(double value, ElectricPotentialUnit unit) | |
| { | |
| return ElectricPotential.From(value, unit); | |
| } | |
| protected override ElectricPotentialUnit GetUnit(ElectricPotential quantity) | |
| { | |
| return quantity.Unit; | |
| } | |
| protected override double GetValue(ElectricPotential quantity) | |
| { | |
| return quantity.Value; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System.Text.Json; | |
| using System.Text.Json.Serialization; | |
| using UnitsNet; | |
| using UnitsNet.Units; | |
| public abstract class QuantityConverter<TQuantity, TUnit> : JsonConverter<TQuantity> | |
| where TQuantity : IQuantity | |
| where TUnit : struct, Enum | |
| { | |
| protected abstract TQuantity FromValueAndUnit(double value, TUnit unit); | |
| protected abstract TUnit GetUnit(TQuantity quantity); | |
| protected abstract double GetValue(TQuantity quantity); | |
| public override TQuantity Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) | |
| { | |
| if (reader.TokenType != JsonTokenType.StartObject) | |
| throw new JsonException($"Expected start of object for {typeof(TQuantity).Name}"); | |
| double value = 0; | |
| TUnit unit = default; | |
| bool valueSet = false; | |
| bool unitSet = false; | |
| reader.Read(); | |
| string valuePropertyName = options.GetPropertyName(nameof(IQuantity.Value)); | |
| string unitPropertyName = options.GetPropertyName(nameof(IQuantity.Unit)); | |
| while (reader.TokenType != JsonTokenType.EndObject) | |
| { | |
| if (reader.TokenType != JsonTokenType.PropertyName) | |
| throw new JsonException("Expected property name"); | |
| string propertyName = reader.GetString(); | |
| reader.Read(); | |
| if (propertyName == valuePropertyName) | |
| { | |
| value = reader.GetDouble(); | |
| valueSet = true; | |
| } | |
| else if (propertyName == unitPropertyName) | |
| { | |
| string unitString = reader.GetString(); | |
| if(!Enum.TryParse<TUnit>(unitString, out var parsedUnit)) | |
| throw new JsonException($"Unknown unit: {unitString} for {typeof(TQuantity).Name}"); | |
| unit = parsedUnit; | |
| unitSet = true; | |
| } | |
| else | |
| reader.Skip(); | |
| reader.Read(); | |
| } | |
| if (!valueSet || !unitSet) | |
| throw new JsonException($"Required property missing for {typeof(TQuantity).Name}"); | |
| return FromValueAndUnit(value, unit); | |
| } | |
| public override void Write(Utf8JsonWriter writer, TQuantity value, JsonSerializerOptions options) | |
| { | |
| writer.WriteStartObject(); | |
| writer.WritePropertyName(options.GetPropertyName(nameof(IQuantity.Value))); | |
| writer.WriteNumberValue(GetValue(value)); | |
| writer.WritePropertyName(options.GetPropertyName(nameof(IQuantity.Unit))); | |
| writer.WriteStringValue(GetUnit(value).ToString()); | |
| writer.WriteEndObject(); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| internal static class SystemTextJsonSerializerExtensions | |
| { | |
| /// <summary> | |
| /// Returns a formatted property name accordingly to provided <see cref="JsonSerializerOptions"/> | |
| /// </summary> | |
| public static string GetPropertyName(this JsonSerializerOptions options, string name) | |
| { | |
| return options.PropertyNamingPolicy == null | |
| ? name | |
| : options.PropertyNamingPolicy.ConvertName(name); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment