Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Cross-Technologies DTO & API Specifications #1378

Open
haimkastner opened this issue Mar 8, 2024 · 0 comments
Open

Support Cross-Technologies DTO & API Specifications #1378

haimkastner opened this issue Mar 8, 2024 · 0 comments

Comments

@haimkastner
Copy link
Contributor

haimkastner commented Mar 8, 2024

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:

  1. Work with UnitsNet across various technologies transparently without any kind of manual conversions.
  2. Standart way how to represent units in API schemas.
  3. Clear OpenAPI specification (and automatically in case the spec is generated from the code object declarations)
  4. 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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant