Skip to content

Conversation

dandro
Copy link

@dandro dandro commented Feb 19, 2024

Overview

Add support for C# version 11 with NewtonsoftJson as/serialization/deserialization library.

Important Notes

  • C# does not have a Unit type, and hence, it results in an error when the target language is C#
  • C# 11 does not support aliases, and hence, it results in an error when the target language is C#
  • C# has strong naming conventions that are followed in the implementation by design. This breaks Serde renaming in some cases. Therefore, I added a configuration flag so the user can turn C# naming conventions off in favour of the Serde renaming feature.

Testing

I've added snapshot tests to most cases except when the Unit type or Aliases are needed, as this is not supported in C#.

@dandro dandro force-pushed the feature/csharp branch 2 times, most recently from 08c1488 to 98e6e28 Compare February 25, 2024 23:28
@dandro dandro mentioned this pull request Apr 4, 2024
@dandro dandro force-pushed the feature/csharp branch from 8db833c to 70e0778 Compare May 6, 2024 00:39
@sanjanabonsai
Copy link

👋🏼 We're currently holding off on including support for new languages as we're in the process of a large refactor to modularize languages.

@dandro
Copy link
Author

dandro commented Jun 28, 2024

👋🏼 We're currently holding off on including support for new languages as we're in the process of a large refactor to modularize languages.

No worries. Yes, I've seen many changes and I am trying to keep up with them so the PR can be reviewed when you have a chance. What would be the rough timeline of the refactoring? Is there anything I could do to help get this in?

@hculea
Copy link
Member

hculea commented Dec 19, 2024

Hi @dandro, thank you so much for this contribution! My apologies for the long turnaround on this.

I am a developer at 1Password and am part of the team that has authored the Python and Go Typeshare implementations (also being a heavy consumer of the Typescript Typeshare). I'm super excited to work with you on this, after I get a bit more familiar with the C# conventions.

To help move this forward, a few ideas around the notes in your PR description:

  • related to the lack of support for unit type in C#, we faced this hurdle with many languages. In general, Units are represented, in Typeshare, with an empty struct. See Swift and Go as examples.
  • related to the C# naming conventions - Typeshare should aim to always translate types idiomatically in the target language. The serde renames are not to be enforced in the types themselves, but only in their JSON serialization/deserialization logic. Looking at what NewtonsoftJson can do about this, would it be feasible to translate serde renames as fields with the JsonProperty tags?
public class Person
{
    [JsonProperty("first_name")]
    public string FirstName { get; set; }
    [JsonProperty("last_name")]
    public string LastName { get; set; }
}

(example for when a #[serde(rename_all = "snake_case")] is applied).

This would be similar to what we do in Go with the struct tags.

  • around the type aliasing - an idea that we explored in other Typeshares is to hard-code a generic type aliasing struct:
public struct TypeAlias<T>
{
    private T value;

    public TypeAlias(T value)
    {
        this.value = value;
    }

    public override string ToString() => value.ToString();

    public T GetValue() => value;
}

and for each type alias defined, to create a specialized instance of this:

public class ActualTypeAliasForString : TypeAlias<string>
{
    public ActualTypeAliasForString(string value) : base(value) { }
}

I'm happy to help delve into each of these options. 😄 As I mentioned, I'm not very familiar with C# and what makes sense here, but I'm eager to help move this forward 🚀

Looking forward to hearing your thoughts! Once again, thank you for this contribution!

@dandro
Copy link
Author

dandro commented Jan 1, 2025

Hi @dandro, thank you so much for this contribution! My apologies for the long turnaround on this.

I am a developer at 1Password and am part of the team that has authored the Python and Go Typeshare implementations (also being a heavy consumer of the Typescript Typeshare). I'm super excited to work with you on this, after I get a bit more familiar with the C# conventions.

To help move this forward, a few ideas around the notes in your PR description:

* related to the lack of support for unit type in C#, we faced this hurdle with many languages. In general, Units are represented, in Typeshare, with an empty struct. See [Swift](https://github.com/1Password/typeshare/blob/b6e6bf1b8459ea9239a46db173d8fef03f88a044/core/src/language/swift.rs#L783) and [Go](https://github.com/1Password/typeshare/blob/main/core/src/language/go.rs#L138) as examples.

* related to the C# naming conventions - Typeshare should aim to always translate types idiomatically in the target language. The serde renames are not to be enforced in the types themselves, but only in their JSON serialization/deserialization logic. Looking at what `NewtonsoftJson` can do about this, would it be feasible to translate serde renames as fields with the `JsonProperty` tags?
public class Person
{
    [JsonProperty("first_name")]
    public string FirstName { get; set; }
    [JsonProperty("last_name")]
    public string LastName { get; set; }
}

(example for when a #[serde(rename_all = "snake_case")] is applied).

This would be similar to what we do in Go with the struct tags.

* around the type aliasing - an idea that we explored in other Typeshares is to hard-code a generic type aliasing struct:
public struct TypeAlias<T>
{
    private T value;

    public TypeAlias(T value)
    {
        this.value = value;
    }

    public override string ToString() => value.ToString();

    public T GetValue() => value;
}

and for each type alias defined, to create a specialized instance of this:

public class ActualTypeAliasForString : TypeAlias<string>
{
    public ActualTypeAliasForString(string value) : base(value) { }
}

I'm happy to help delve into each of these options. 😄 As I mentioned, I'm not very familiar with C# and what makes sense here, but I'm eager to help move this forward 🚀

Looking forward to hearing your thoughts! Once again, thank you for this contribution!

Thank you so very much for getting back to me and spending the time to look into this. I will start looking into each one of these suggestions and hopefully create some commits soon.

Create basic language implementation.
Start adding tests.

Add snapshot tests

Update slice type to map to IEnumerable instead of Array.
Drop support for Unit type and return an error.

Support anonymous structs

Update slice of user type test snapshot

Support namespace option

Support serialization with json attributes

Remove EnumLabel and use EnumMember attribute instead.
Update all test snapshots according to the new changes.

C# without naming convention option

Add required attribute

For newtonsoft json to require a non optional property, the property has
to have the required attribute. Otherwise, it allows it to be null and a
default value is provided.
The order of elements in the output file has been updated
Re add CSharp imports and update configuration and Args handling
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants