Start a new topic

JSON -> object - parsing object graphs

Hi! I'm evaluating how can duocode makes LOB application development easier. My goal is to write an html client application in C# (using duocode) with maximizing code sharing (DTO classes) between the client and the ASP-NET Core server-side with its rest services. For example, there is a simple (dummy) person-pet database like this: class Person { public string Name { get; set; } public int Age { get; set; } public List<Pet> Pets { get; set; } } class Pet { public string Name { get; set; } public int Age { get; set; } } there are 2 simple rest web methods. one for getting a list of Persons , an other for getting a Person by its name. [HttpGet("getAllPerson")] public List<Person> GetAllPerson() {...} [HttpGet("getPerson/{name}")] public Person GetPerson(string name) {...} in the client side the response of ajax call comes in JSON format, so i would like to parse it into List<Person> and Person instances to use them in client-side code. 1. I've tried the most simple and convenient way: Person person = DuoCode.Dom.Global.JSON.parse(response); unfortunately it does not work as it was explained in the past. 2. You suggested to solve it using this kind of helper classes: [Js(Extern = true)] class JsPerson { public extern string name { get; } public extern int age { get; } public extern List<Pet> pets { get; } // public extern JsList<JsPet> pets { get; } } [Js(Extern = true)] class JsPet { public extern string name { get; } public extern int age { get; } } public class XConverter { public static Person createPerson(JsPerson jsp) { Person p = new Person(); p.Name = jsp.name; p.Age = jsp.age; this.Pets = new List<Pet>(); foreach(JsPet jspet in jsp.pets) thi.Pets.Add(createPet(jspet)); return p; } public static Pet createPet(Pet jsp) { Pet p = new Pet(); p.Name = jsp.name; p.Age = jsp.age; return p; } } it does work while there is no List (or other collection) field in the DTO classes. But how to handle List? i've tried to create a helper for List class (beacause the simple way did not worked) too like this: [Js(Extern = true)] public class JsList<T> { [Js(Name="Count")] // Name="m_Size" public extern int Count { get; } [Js(Name="Item")] // Name="m_item" public extern T this[int index] { get; set; } public extern void Add(T item); public extern IEnumerator<T> GetEnumerator(); } but the names i've given for properties ( in the Js(Name="...") attributes ) simply does not work... and maybe it is a wrong way to define classes like this for standard collection classes... At this point i've decided to ask You... maybe i'm on the wrong way... Could you please give me some suggestions ini how to handle these standard collection classes (list, set, dictionary)? Is it really impossible to find a general way without these ugly code-duplicator helper classes? Because of the need of writing these helper class my original goal is dead, but if these classes can be generated in some way then it is acceptable for me. Any ideas? Thanks OneDeveloper

This forum engine is not the best.... horrible is a much better word...   cannot paste newlines here so i have to write the all here in this small box which is fixed in size... :S    Who likes this?

Formatted version:

Hi!

I'm evaluating how can duocode makes LOB application development easier.

My goal is to write an html client application in C# (using duocode) with maximizing simpicity and code sharing (DTO classes) between the client and the ASP-NET Core server-side with its rest services.

For example, there is a simple (dummy) person-pet database like this:
   class Person
   {
      public string Name { get; set; }
      public int Age { get; set; }
      public List<Pet> Pets { get; set; }
   }
   class Pet
   {
      public string Name { get; set; }
      public int Age { get; set; }
   }

there are 2 simple rest web methods. one for getting a list of Persons , an other for getting a Person by its name.
   [HttpGet("getAllPerson")]
   public List<Person> GetAllPerson() {...}

   [HttpGet("getPerson/{name}")]
   public Person GetPerson(string name) {...}

in the client side the response of ajax call comes in JSON format, so i would like to parse it into List<Person> and Person instances to use them in client-side code.

1. I've tried the most simple and convenient way:
       Person person = DuoCode.Dom.Global.JSON.parse(response);
      unfortunately it does not work as it was explained in the past.

2. You suggested to solve it using this kind of helper classes:
[Js(Extern = true)]
class JsPerson
{
   public extern string name { get; }
   public extern int age { get; }   
   public extern List<Pet> pets { get; }
  // public extern JsList<JsPet> pets { get; }
}
[Js(Extern = true)]
class JsPet
{
   public extern string name { get; }
   public extern int age { get; }
}

public class XConverter
{
   public static Person createPerson(JsPerson jsp)
   {
      Person p = new Person();
      p.Name = jsp.name;
      p.Age = jsp.age;
      this.Pets = new List<Pet>();
      foreach(JsPet jspet in jsp.pets)
         this.Pets.Add(createPet(jspet));
      return p;
}
public static Pet createPet(Pet jsp)
{
   Pet p = new Pet();
   p.Name = jsp.name;
   p.Age = jsp.age;
   return p;
}
}

it does work while there is no List (or other collection) field in the DTO classes.
But how to handle List?
i've tried to create a helper for List class (beacause the simple way did not worked) too like this:


[Js(Extern = true)]
public class JsList<T> {
   [Js(Name="Count")] // Name="m_Size"
   public extern int Count { get; }
   [Js(Name="Item")] // Name="m_item"
   public extern T this[int index] { get; set; }  
   public extern void Add(T item);
   public extern IEnumerator<T> GetEnumerator();
}

but the names i've given for properties ( in the Js(Name="...") attributes ) simply does not work...
and maybe it is a wrong way to define classes like this for standard collection classes...

At this point i've decided to ask You... maybe i'm on the wrong way...
Could you please give me some suggestions ini how to handle these standard collection classes (list, set, dictionary)?
Is it really impossible to find a general way without these ugly code-duplicator helper classes?
Because of the need of writing these helper class my original goal is dead, but if these classes can be generated in some way then it is acceptable for me.

Any ideas?

Or am i a pervert who want to do it in a simple elegant way?   

Thanks
   OneDeveloper

ps: i've tried to do so using bridge.net, but i wasn't able to solve this.  maybe it is impossible?

here is an example like this using duocode Try:


classes are named A and B instead of Person and Pet, but the point is the same...


http://duoco.de/try#K4Zwlgdg5gBAygTxAFwKYFsDcAoUlaIoYB0AwgPYA2lqAxsmORCMQOKoSoBOYtOe0GABFg5CgBNUxAErAIDdKhzYIAQ0UgADqtqoYACVTVyIseUnYA3thgxNwAEaVeMFKoa0YtSqpAgYAApc5FBc6jYw1ra29k4ubh4wAG7kYOIwALKqkAAUAJQRtlHRtoRo6GRMIFRSAOo8aAAykKg5AESGxsKiEqhteTgA9IMltrRVyK7IPIJcqFpVegC8MG2WADptAGIAjJsAXDCbcOSKACoAFvibADRHbQBCe22Hlve7B/cA8sgX3JfXNowAC+q2ww1G0QA1Ks7psHiBPm83psPi9vr9/ldBM8QXcUdtnodNj8/lwAYIAEybEG04FtHCQwrRACCMAAHqoYCtOAB3GAs/KM0ac4i7bmrdnshnM2yip4SvkwB5C2Uc1TEJ5inYStoIBAyyHy/w81D85ooAA8DwAfKqjRqEcQWeJxDklSq2qpvf0Bmrjc7Xe6zcr2g5w77hSU1WUSBRmDViPUwE0Wu1iBnRbtDkCYVmdn7IbGKvHqjQkw1UM1OOnM46dtr9rn1ZqG7tC6MAGbkOY6C4wHIPGAOGCQFsIgqQ0pIcqVBPl5OpmttDOr4gORvNjftqPRNVqlAzWBzBbMZbdMySYhCU5sSjkByqSjEABScC+ADliIf8GBOwgck5DsSmLOcyzqStq1aE9NEWYC90hF8QDZAArEAuRWUxemvW9WHvR9nzfT9iG0LgQGg+ZYLPP0AEhbGGJDUPQiUkOIOZO24DhdBZEBLUYu0YLg3dbDZDCYCVQU0NUeDbAPaZ8FcMSNV2YSYBjGc4yqRNFyrNMVwzZSdhzGAYUMmT4A0kstIXSC9NXetNxMmAHJ3NVu17Wh+0HYdRwgZzNRAScp1A0ttNs5dV23Iyt21P11KIKz5wglNdOXB4ED0LDzD6eDgQiPLZJiRxnE8bxfH8NliiKuJPB/QRxTeKBUGQTBXGa1qCuiWISuVZUdUa9q2pakFmW6lwLWQa0bWVfxLCa4byJavLRuKlxBTySJOuqnq2RyRiYCkjaquiX4wBYcUVik7VVNOlgFVNfkVSup5zNugLFRDCapvtUY6tgE0L2wm8Kjwh8n1fd8vz+v8AOewLVKQxo+JAW0YGoCUsqvYG7zBwjIZI1QyNaeG3J7AdIEmMAJQABlaqnLTR590AAfTgMAAC8lBMqEwCCyE3qdF03Q9HJqGIFmAElyhAABtMAAF08j9CEux7VA+wHJChzQkcxzhgoVanAWWCF4NHpyHWlaGEZVa4cn5FHGm6ZgS1LvQgLKjkYaoR5g2baNq47pNoMRbhuXFdy/KIgiMbSp8PxeuO2OpiPGAGpgebWsWjqVpq0Mjq2uxVs8FU/pgTsC0iGA3ou8udkwQvk6HPaUYOkAHCOtUa51N2ot3TrltsGWkJyABRdk0C4PyVmmYBUDyeWY+Lrx4/8fak+X1AJ+4Pyy/TzOhpzkpk63ye/K1vqq4P7ORuPzft6nmBEbOyatemhFImv9qB+wCJh5AMeD9p7Vy4HPBeS885lQThfDeedT47xTgpfeg0b4/wgT1KBa8QBIzONNY6/8cgfnUKgJYbQWZs05v0Red884UxgOQjmeg5rf2ZAQohihSGS2llQ3OPUzgy3lvQ5mUsMCzUzj/QqMACHjzPhKWe89qFF0gavJ+2CX6WlwZEVhI92EkLaBQL2PCaE9XgY/OhBiHYDWGoXNhxDSEiPQEYrq99ZFnGroHOWDtICSHZIIqxWdBqNxcQglIaQBRBjcSldA8ET5AJgBLUeEBgCKDCMgHsGjprsGQIk5J3B3A9h+p1aOeUgAAA

DuoCode fully supports reflection, see our UnitTest sample.

Use classic Activator.CreateInstance() for creation, including generic classes.

Don't forget to turn on Reflection for assembly, using [CompilerOptions(ReflectionLevel=ReflectionLevel.Partial)] attribute or via Project properties page > DuoCode tab.


But personally I think for no really big projects DTO (data transfer objects) approach is easier and even better, just because check is done at compilation time and not at runtime, easy to handle, debug, history of change, backward/forward compatibility and more.


Sorry for late replay,

Daniel

Hi Daniel!


Thanks for your reply again! I will use the suggested Activator + Reflection way.

(I will continue my work on this part of the project in the next days, so it didn't come late :) )


You did write DTO approach is easier and better for smaller projects.


My approach seems "DTO approach" for me because these Person and Pet classes are really DTO classes ( they are POCO classes, not contains anything entity-specific or whatever else ), which are served by rest api methods for the clients. 

Maybe it caused the misunderstanding that i wrote "there is a simple (dummy) person-pet database like this", but i want to make it clear, that i don't want to serve directly my entity class instances through the rest api, i would like to serve real DTO classes.


So do you agree that my approach is DTO approach?  If not, then please explain me shortly what do you mean as "DTO approach"!


Thank You,

  OneDeveloper

Such DTO objects are not JSON friendly, since they are C# to JS classes have properties and even properties which are List<>.

I suggest to create clean JS classes by inheriting from JsInterface (similar to interface in TypeScript, it's just a declaration no actual class is behind), like this:

Like this: 

public class JsA : JsInterface
  {
    public string F1 { get; set; }
    public JsB B1 { get; set; }
    public JsB[] Bs {get; set;}
  }

  public class JsB : JsInterface
  {
    public extern string F1 { get; set; }
  }


Later you can create constructor to create C# classA from JSON like class JsA, this way:

  

public ClassA
{
  public ClassA(JsA jsonA) { ... }
}

 

Hopes this help,

Daniel 


Hi Daniel!


Thanks for your answer!


so using array instead of any list-like thing in these clean JS classes will do the job for lists... i will try it.

Anyhow it is still a manual job with creating/generating additional classes, which i would like to avoid.


what about a generic instance builder which uses reflection to build the class instances from json string?

Is it possible to write one? Is duocode powerful enough for this ( i mean in areas of reflection and generic )?


There are some other solutions for typescript (because duocode generates typescript also), like TypedJson (https://github.com/JohnWhiteTB/TypedJSON) ...

could it help in some way to include typecript into the soup? 


Also c#html5 (which is build on the top of jsil) has an own JSON serializer/deserializer implementation, but i had no time to check it at all...


these are just my silly ideas, but You can analyze them from an insider POV...


Anyhow, it is just only me who wants to use this type of code minimizing and sharing between client- and server-side code?

Login or Signup to post a comment