Description
Is your feature request related to a problem? Please describe.
Request related
As part of the powerful and wide support in multiple languages in the unit definition, I think it can be cool to standardize the way how unit is represented in the API spec, and how it will be exposed/loaded.
Implementing in all UnitsNet-based libraries a similar API DTO to load/expose and the same JSON schema standard of how the unit is represented, will give the benefits of:
- Work with UnitsNet across various technologies transparently without any kind of manual conversions.
- Standart way how to represent units in API schemas.
- Clear OpenAPI specification (and automatically in case the spec is generated from the code object declarations)
- Human readable unit representation in the API schema, and easy to work with anyway.
See also haimkastner/unitsnet-js#29 for real-world, probably common use-case between C# backend and TypeScript frontend.
Currently, sterilizing is supported in the library, but not as a common, standard, unit dedicated and easy-to-use API.
Describe the solution you'd like
The JSON standart DTO will look like this:
{
"value":100.01,
"unit":"Meter"
}
As part of the full JSON API payload something like:
{
"someInfo":"someValue",
"someInfoLength":{
"value":100.01,
"unit":"Meter"
}
}
See an OpenAPI unitsnet-openapi-spec example schema.
A basic and naive prototype of how it will be in C#
using System;
using UnitsNet;
using UnitsNet.Units;
using System.Text.Json;
public class LengthDto
{
class JsonDto
{
public double value { get; set; }
public string unit { get; set; }
}
public LengthDto(double value, LengthUnit unit)
{
this.value = value;
this.unit = unit;
}
public double value { get; set; }
public LengthUnit unit { get; set; }
public string ToJson()
{
JsonDto jsonInterface = new JsonDto { value = this.value, unit = this.unit.ToString() };
return JsonSerializer.Serialize(jsonInterface);
}
public static LengthDto fromJson(string json)
{
JsonDto jsonInterface = JsonSerializer.Deserialize<JsonDto>(json);
Enum.TryParse<LengthUnit>(jsonInterface.unit, out LengthUnit newUnit);
return new LengthDto(jsonInterface.value, newUnit);
}
}
public static class LengthExtensions
{
public static Length fromDto(this Length length, LengthDto lengthDto)
{
return new Length(lengthDto.value, lengthDto.unit);
}
public static LengthDto toDto(this Length length, LengthUnit unit = LengthUnit.Meter)
{
return new LengthDto(length.As(LengthUnit.Meter), unit);
}
}
public class Program
{
public static void Main()
{
Length lengthValue = Length.FromMeters(100.01);
string json = lengthValue.toDto().ToJson();
Console.WriteLine(json); // {"value":100.01,"unit":"Meter"}
LengthDto newLengthDto = LengthDto.fromJson(json);
Length newLengthValue = new Length().fromDto(newLengthDto);
Console.WriteLine(newLengthValue.Meters); // 100.01
}
}
A similar implementation I have created for the JS package haimkastner/unitsnet-js#32 & haimkastner/unitsnet-py#18
TypeScript usage (docs)
// Create a Length unit object
const length = Length.FromMeters(100.01);
// Obtain the DTO object, represented by the default unit - meter
const lengthDto: LengthDto = length.toDto(); // {"value":100.01,"unit":"Meter"}
// Obtain Length object from lengthDto
const newLength: Length = Length.FromDto(lengthDto);
Similar for the Python package (docs):
# Create a Length unit object
length = Length.from_meters(100.01)
# Obtain the DTO object as json, represented by the default unit - meter
length_dto_json = length.to_dto_json() # {"value":100.01,"unit":"Meter"}
# Load JSON to DTO, and load
length_from_dto = Length.from_dto_json(length_dto_json)
Describe alternatives you've considered
To do it manually.
Additional context
See an example of the Python Length implementation of the DTO class and the unit API example