1

I would like to find a way to map multiple json strings to a single object in c#. I am currently using Newtonsoft.Json in a solution, but I am not opposed to using something else.

Here is an example using a Unit object and different json strings.

General object

public class Unit
{
    public string Year { get; set; }
    public string Model { get; set; }
}

Example json objects

{
    "UnitYear":"2018",
    "UnitModel":"F250 Super Duty"
}

{
    "AssetYear":"2019",
    "AssetModel":"Corvette Stingray"
}

If I were to run each json string through the Newtonsoft.Json deserialize method i'd want the output to be like so.

Unit1 : Year = 2018, Model = F250 Super Duty
Unit2 : Year = 2019, Model = Corvette Stingray

For now I'll store the mappings in a dictionary then later on transfer it to a database structure.

private static Dictionary<string, List<KeyValuePair<string, string>>> Units = new Dictionary<string, List<KeyValuePair<string,string>>>
{
    { "0000001", new List<KeyValuePair<string,string>>
        {
            new KeyValuePair<string,string>("Year", "UnitYear"),
            new KeyValuePair<string,string>("Model", "UnitModel")
        }
    },
    { "0000002", new List<KeyValuePair<string,string>>
        {
            new KeyValuePair<string,string>("Year", "AssetYear"),
            new KeyValuePair<string,string>("Model", "AssetModel")
        }
    },
};

I found that Newtonsoft.Json has a customer converter that can be implemented. The code I found on the website was very lacking. I did notice that you have to instantiate the custom converter to pass into the deserialize method. I'm think that I can use the constructor to pass in the identifier for the json that I'm converting.

Unit u1 = JsonConvert.DeserializeObject<Unit>(json, new GenericConverter("0000001"));
Unit u2 = JsonConvert.DeserializeObject<Unit>(json, new GenericConverter("0000002"));

But I am lost as to how I utilize the ReadJson that you have to override.

Any help here would be very appreciated.

Thank you

Jared
  • 175
  • 1
  • 13

2 Answers2

0
 This will be used for mapping your response to the model JsonConvert.DeserializeObject<Unit>(response)

public class Unit
{
    public string UnitYear { get; set; }
    public string UnitModel { get; set; }
}

Make sure that the property names are the same names as your json object that you are passing through 
0

The best practice would be to make the JSON describe the object a little better:

"Unit":{
    "UnitYear":"2018",
    "UnitModel":"F250 Super Duty"
}

"Asset":{
    "AssetYear":"2019",
    "AssetModel":"Corvette Stingray"
}

With what you have now, you could add a method to each class:

public bool IsValid()
{
    return Model != null && Year.Date == DateTime.MinValue;
}

And then do the following for each class you want to test:

        var stringUnit = "{\"UnitYear\":\"2018\",\"UnitModel\":\"F250 Super Duty\"}";
        var assetUnit = "{\"AssetYear\":\"2019\",\"AssetModel\":\"Corvette Stingray\"}";


        var unit = Newtonsoft.Json.JsonConvert.DeserializeObject<Asset>(stringUnit);

        if (unit.IsValid())
        {
            Console.WriteLine(unit.AssetModel);
        }
        else
        {
            Console.WriteLine("Json can't convert this");
        }

What I'd be more inclined to look at doing would be something like this:

Create a type Enum and a Unit Class:

public class Unit
{
   public DateTime DateTime { get; set; }
   public string Model { get; set; }
   public UnitType UnitType { get; set; }

   public bool IsValid()
   {
       return Model != null && DateTime == DateTime.MinValue || UnitType != UnitType.Unknown;
    }
 }

And then create an Enum for Newtonsoft's JSON Converter:

[JsonConverter(typeof(StringEnumConverter))]
public enum UnitType
{
    Unknown = 0,
    Asset,
    Unit
}

And then you can try and desrialize all of the JSONs exactly the same:

string jsonString = "{\"Year\":\"2019\",\"Model\":\"Corvette Stingray\",\"UnitType\":\"Asset\"}";
var resultUnit = JsonConvert.DeserializeObject<Unit>(jsonString);

if (resultUnit.IsValid())
{
    // This works, do the right thing. When the type matters access resultUnit.UnitType
}
else
{
   //Throw an exception, really badly formed or an Unknown type
}
Austin T French
  • 5,022
  • 1
  • 22
  • 40