0

In a dotnet microservice architecture, to avoid exposing my data model and its logic, I am willing to add a POCO data model layer following a mechanism: fullDataModel>json>pocoDataModel. Here is my reduced fullDataModel

public class MyDto
{
    public string Name { get; set; }
    public AnExternalNamespace.MyExternalType ExternalObject { get; set; }
}

To implement the above mechanism, I am using NJSonSchema CSharpGenerator as follow:

// generate Json schema from ConsoleApp1
JsonSchema schema = await JsonSchema.FromFileAsync("MyDto.txt");
CSharpGeneratorSettings settings = new CSharpGeneratorSettings
{
    ClassStyle = CSharpClassStyle.Poco,
    Namespace = "MS1Namespace",
    GenerateDataAnnotations = true
};
var generator = new CSharpGenerator(schema, settings);
var modelFile = generator.GenerateFile();

// generate the C# file in a another ConsoleApp2 for testing purpose
using (StreamWriter writer = new StreamWriter("..\\ConsoleApp2\\MyDtoFromJson.cs"))
{
    writer.WriteLine(modelFile);
}

Problem, the MyDto class refers to a type which comes from an external library (AnExternalNamespace.MyExternalType). But the mechanism I implemented does not preserve this type of reference, rather it generates a type bounded to each namespace associated with each microservice I use that implement this type. Have a look at the C# generated file which is bounded to MS1Namespace

namespace MS1Namespace
{
    [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.8.0.0 (Newtonsoft.Json v13.0.0.0)")]
    public partial class MyExternalType
    {
        [Newtonsoft.Json.JsonProperty("Name", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
        public string Name { get; set; }

        [Newtonsoft.Json.JsonProperty("Description", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
        public string Description { get; set; }

    }

    [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.8.0.0 (Newtonsoft.Json v13.0.0.0)")]
    public partial class MyDto
    {
        [Newtonsoft.Json.JsonProperty("Name", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
        public string Name { get; set; }

        [Newtonsoft.Json.JsonProperty("ExternalId", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
        public MyExternalType ExternalObject { get; set; }
    }
}

In other words, with this mechanism, MyExternalType is kind of redefined relative to each MSnNamespace for every microservice (1 to n) where it is embedded. On the contrary, I would like to be able to receive objects that refer to the type defined in the AnExternalNamespace each time I send a request to these microservices. That would allow me treat the data of same type coming from these different microservices in a unified way with the unique AnExternalNamespace.MyExternalType

I have tried to play with Json annotations in MyDto class. For example by doing this:

[JsonProperty(TypeNameHandling = TypeNameHandling.Auto)]
public MyPublicLibrary.MyExternalType ExternalId { get; set; }

This does not allow to get out of the MS1Namespace scope to which all the auto-generated classes are bounded.

So, the only solution I see to overcome this for now is to implement an explicit&implicit cast in each microservice embedding this type from MSnNamespace.MyExternalType to AnExternalNamespace.MyExternalType. But I was thinking NJSonSchema settings could offer me a more elegant way to deal with this situation. Am I missing something here? Do you see any other options or better practice while continuing keeping passing through the Json serialization/deserialization process?

Thanks in advance for your help!

Gipe
  • 1
  • 1

0 Answers0