0

I have a JSON string where records can change. I'm using public partial classes for every level I have in my JSON string. I'm copying it to a DataTable since I need it in my SQL-Server. I'm calling JSON like this:

StringReader sr = new StringReader(json);
Newtonsoft.Json.JsonTextReader readera = new JsonTextReader(sr);
object result = (Welcome)jsona.Deserialize(readera,typeof(Welcome));

Welcome w = (Welcome)result;

DataTable da = w.Result.Records.ToDataTable(); 

So for example, my JSON can contain:

ID,Name,Value

But other JSON might contain:

ID,Address,City,PostcalCode

My Class looks like this now:

public partial class Record
{
    [JsonProperty("Col1")]
    public DateTimeOffset Col1 { get; set; }

    [JsonProperty("Col2")]
    public long Col2 { get; set; }

    [JsonProperty("Col3")]
    public DateTimeOffset Col3 { get; set; }

    [JsonProperty("Col4")]
    public long Col4 { get; set; }

    [JsonProperty("Col5")]
    public string Col5 { get; set; }

How would I make this Dynamic? I really don't have a clue.

Gonçalo Peres
  • 11,752
  • 3
  • 54
  • 83
SqlKindaGuy
  • 3,501
  • 2
  • 12
  • 29

2 Answers2

1

You can use dynamic datatype instead of class. here the example using Json.net

JObject obj = JsonConvert.DeserializeObject("{ 'Name': 'Smith', 'Address': { 'City': 'New York', 'State': 'NY' }, 'Age': 28 }");

var properties = obj.Properties();
foreach (var prop in properties)
{
    string key = prop.Name;
    object value = prop.Address;
    int age = prop.Age;         
}
Tech Yogesh
  • 427
  • 4
  • 18
1

You can create a class via a string and compile and load it at runtime and set the values via reflection.

In this example I reduced the new class to just one property.

public Type BuildType(string propertyName)
    {
        var code = @"
            using System;
            namespace MyNamespace
            {
                public class MyClass
                {
                    public object " + propertyName + @" { get; set; }
                }
            }";

        var provider = new CSharpCodeProvider();
        var parameters = new CompilerParameters
        {
            GenerateInMemory = true,
            GenerateExecutable = false
        };

        var results = provider.CompileAssemblyFromSource(parameters, code);

        // Check Errors
        if (results.Errors.HasErrors)
        {
            var sb = new StringBuilder();
            foreach (CompilerError error in results.Errors) 
            {
                sb.AppendLine(string.Format("Error ({0}): {1}", error.ErrorNumber, error.ErrorText));
            }
            throw new InvalidOperationException(sb.ToString());
        }
        var assembly = results.CompiledAssembly;
        var classInstance = assembly.GetType("MyNamespace.MyClass");

        return classInstance;
    }
Mardukar
  • 415
  • 2
  • 11