Search code examples
c#jsondatareader

Dynamically create JSON object for datareader results, regardless of what they look like?


Right now I'm using Newtonsoft.json with my OdbcConnection and manually creating objects for each query I run. It looks something like this:

Classes:

public class payload
{
    public string id;
    public string type;
    public DateTime timestmap;
    public object data;
}
public class resultPhrLastTime
{
    public string facilityId;
    public string type;
    public string time;
} 

Code:

payload result = new payload();
var resultList = new List<resultPhrLastTime>();
result.id = "someid";

//connection stuff

        while (reader.Read())
        {
            var t = new resultPhrLastTime();
            //if (verbose) log(reader[0].ToString());
            t.facilityId = reader[0].ToString();
            t.type = reader[1].ToString();
            t.time = reader[2].ToString();
            resultList.Add(t);
        }

    result.data = resultList;
    result.timestmap = DateTime.Now;
    result.type = "complex";
    string output = JsonConvert.SerializeObject(result);

This works fine, but every time I add a new query to my app (of which there will be many) I have to create a new custom class if the data looks different at all.

I would like to find a way to convert the entire reader object to JSON regardless of the format, so it may look like this:

SQL Result:

2814814

JSON:

result: {
   timestamp: 2016-09-10 8:15,
   data: { '2814814' }
}

or it may look like this:

SQL Result:

Apple  | 59    
Orange | 17

JSON:

result: {
   timestamp: 2016-09-10 8:15,
   data: {[ 
      'Apple':'59',
      'Orange':'17'
   ]}
}

Or there could be 5 columns...

Is there a way to do this?


Solution

  • You can use the dynamic type of c#

    public class payload
    {
        public string id;
        public string type;
        public DateTime timestmap;
        public dynamic data;
    }
    
    
    payload result = new payload();
    var resultList = new List<Dictionary<string, dynamic>>();
    result.id = "someid";
    
    //connection stuff
    
    while (reader.Read())
    {
    
        var t = new Dictionary<string, dynamic>();
        for (var i = 0; i<reader.FieldCount; i++)
        {
            t[reader.GetName(i)] = reader[i];
        }
        resultList.Add(t);
    }
    
    result.data = resultList;
    result.timestmap = DateTime.Now;
    result.type = "complex";
    string output = JsonConvert.SerializeObject(result);
    

    The dynamic type is handled by JsonConvert automatically.

    You can also make the data field of the payload to a dynamic to handle single field results like in your first JSON example.