0

I need to convert JSON object to entity, I have many entities and I don't want to write my code some times, so I built an entity-base class and I want to do deserialize to entity (without know which derived-entity call to the base-entity).

Can I do it?

This is my base class (It is abstract class)

  public abstract class AbstractEntity
{
    EntityState EntityState { get; set; }
    DateTime CreatedDate { get; set; }
    DateTime? ModifiedDate { get; set; }
    string CreatedBy { get; set; }
    string ModifiedBy { get; set; }

    public EntityState getEntityState()
    {
        return EntityState;
    }
    public void SetEntityState(EntityState entityState)
    {
        EntityState = entityState;
    }            
}

The first ent:

public class TABLE1: AbstractEntity
{
    public TABLE1();

    public string ID{ get; set; }

    public string ADDRESS{ get; set; }
    public virtual ICollection<TABLE2> TABLE2 { get; set; }
}

The second ent:

public class TABLE2: AbstractEntity
{
    public TABLE2();

    public string ID{ get; set; }

    public string ADDRESS{ get; set; }
    public virtual TABLE1 TABLE1{ get; set; }
}
Junius
  • 589
  • 2
  • 12
  • 41
user1012506
  • 2,048
  • 1
  • 26
  • 45
  • Possible duplicate of [How to Convert JSON object to Custom C# object?](https://stackoverflow.com/questions/2246694/how-to-convert-json-object-to-custom-c-sharp-object) – CodeNotFound Jun 10 '18 at 06:23
  • Did the example in the link is generic convert? The base-class does not know the entity name – user1012506 Jun 10 '18 at 06:26
  • How do you discern from the JSON which entity type you want (as a human being, not as a computer)? You could use a `JsonConverter` – ProgrammingLlama Jun 10 '18 at 06:29
  • 1
    Possible duplicate of [Deserializing polymorphic json classes without type information using json.net](https://stackoverflow.com/questions/19307752/deserializing-polymorphic-json-classes-without-type-information-using-json-net) – ProgrammingLlama Jun 10 '18 at 06:31
  • @user1012506 If I understand your question correctly, do you want to deserialize your JSON object to an entity or type which doesn't need to know the base class /type to derived from? – Junius Jun 10 '18 at 06:32
  • juniuz, Yes, You got me right... – user1012506 Jun 10 '18 at 06:36
  • john, My question not duplicated because I have more than 2 entities.. "is_album" property is wrong use of generic – user1012506 Jun 10 '18 at 06:43
  • So, because the other question isn't a word for word duplicate of yours, it's invalid? It's true that you can lead a horse to water but you can't make it drink. – ProgrammingLlama Jun 10 '18 at 07:21
  • 1
    Sorry for not accepting, The map in the answer leans on boolean proprty than not relevant with more than 2 entities. – user1012506 Jun 10 '18 at 07:31
  • 1
    @user1012506 - the basic idea of [Deserializing polymorphic json classes without type information using json.net](https://stackoverflow.com/q/19307752/3744182) is to create a `JsonConverter` that pre-loads the JSON for each `AbstractEntity` into a `JToken` then chooses appropriate subtype by checking for the presence and values of appropriate properties. See [Json Array to Custom Object Mapping in C#](https://stackoverflow.com/q/47578150/3744182) and [JsonConverter with Interface](https://stackoverflow.com/q/33321698/3744182) for other examples of such. – dbc Jun 10 '18 at 07:37
  • While that's true, I'm sure you are a smart enough person to extrapolate that you could use a string, e.g. "type" and check the value of that to decide which C# type you need. For example: `string type = item["type"].Value();` After realising that, I'd argue that the duplicate is entirely relevant to your question. – ProgrammingLlama Jun 10 '18 at 07:37
  • Does in your answer I can use just one time in deserialize? thats I want. not duplicated of deserialize, I write Infrastructures and not fix bugs... – user1012506 Jun 10 '18 at 07:41
  • @user I've added an answer as community wiki to help you understand how the duplicate might apply to your situation. – ProgrammingLlama Jun 10 '18 at 08:10

2 Answers2

4

You can use JObject from Newtonsoft.Json library. This is the site https://www.newtonsoft.com/json to refer on how to use it. And, a lot of code samples as well can be found here https://www.newtonsoft.com/json/help/html/Samples.htm.

For example:

using Newtonsoft.Json.Serialization;

    public void Foo(string jsonData){
    var objData = (JObject)JsonConvert.DeserializeObject(jsonData); // Deserialize json data

    dynamic jObject = new JObject();
jObject.ID = objData.Value<string>("ID");
jObject.Address = objData.Value<string>("Address");
jObject.TABLE2 = objData.Value<JArray>("TABLE2");
    }

In the above code sample, jObject which has a dynamic type that can be converted to which type you want.

Hope this helps.

Junius
  • 589
  • 2
  • 12
  • 41
  • Junius, Thanks! So I don't need any changes in the base class? – user1012506 Jun 10 '18 at 07:22
  • 1
    No worries @user1012506, you don't have to change your base class if that's want you want. It's just simply that you can instantiate a type object without having an actual type by using `dynamic` keyword. You can refer to this SO answer for more details on `dynamic` https://stackoverflow.com/questions/2690623/what-is-the-dynamic-type-in-c-sharp-4-0-used-for – Junius Jun 10 '18 at 07:33
  • OK, So I can't write a generic deserialize , this is the answer! (I asked for deserialize in the base class on purpose not write duplicate code) – user1012506 Jun 10 '18 at 07:37
  • @user1012506, yes you can use type of `T` which deserialize your json data. As example: `var fooBar = JsonConvert.DeserializeObject(jsonData);` – Junius Jun 10 '18 at 07:42
3

The duplicate linked is probably a better general-purpose solution:

public class AbstractEntityConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(AbstractEntity);
    }

    public override object ReadJson(JsonReader reader,
        Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject item = JObject.Load(reader);
        var type = item["TYPE"].Value<string>();
        switch (type)
        {
            case "TABLE1":
                return item.ToObject<TABLE1>();
            case "TABLE2":
                return item.ToObject<TABLE2>();
            default:
                return null;
        }
    }

    public override void WriteJson(JsonWriter writer,
        object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

Usage:

string json = "{\"TYPE\":\"TABLE1\",\"CreatedDate\":\"2018-06-10T08:00:00.000Z\",\"CreatedBy\":\"John\",\"ID\":\"1\",\"ADDRESS\":\"1 Road Street\",\"TABLE2\":[{\"CreatedDate\":\"2018-06-10T08:00:00.000Z\",\"CreatedBy\":\"John\",\"ID\":\"2\",\"ADDRESS\":\"2 Road Street\"}]}";
var settings = new JsonSerializerSettings()
{
    Converters = new List<JsonConverter>()
    {
        new AbstractEntityConverter()
    }
};
var obj = JsonConvert.DeserializeObject<AbstractEntity>(json, settings);

Of course, you can define your JsonSettings at a central location so that you don't have to keep writing the declaration every time you use it.

P.S. I've opted to assume a "type" property since you didn't show your JSON, or your method of determining which class to deserialize to. Replace with your own logic as needed.

Try it online

ProgrammingLlama
  • 36,677
  • 7
  • 67
  • 86