Let's say that in my WebAPI I'm receiving a json like this:
{
prop1: "sometext",
prop2: 123,
prop3: true,
prop4: [1,2,3,4,5],
prop5: ["text1", "text2", "text3"]
}
To work with this data, I transform it into this: dynamic data = System.Web.Helpers.Json.Decode(json);
. In most cases it's really easy to work with it, but I'm struggling with a situation where I need to repass this data to a database. Most conversions are pretty straightforward, making it easy to iterate over the DynamicJsonObject and send the information to the DB.
My big problem is dealing with properties like prop4
and prop5
. This array is being converted to a DynamicJsonArray. To convert it to a primitive array, I'm currently using this:
Array arr = (Array) data["prop4"];
data["prop4"] = arr.Cast<Int32>().ToArray();
The code above works fine and it successfully converts the property value to an integer array that can be sent to the DB. However, when I do it with the string array:
Array arr = (Array) data["prop5"];
data["prop5"] = arr.Cast<string>().ToArray();
The data["prop5"]
value isn't changed, and when I inspect it's value, it still points to the type System.Web.Helpers.DynamicJsonArray
. Why does this happen?
Also, the thing is that I'm not experienced on working with dynamic objects in C# and I use that because in my situation I do not always know what properties the JSON I'm receiving is going to have. Is there a cleaner way to make this kind of conversion? Actually, is there any need to use dynamic objects to deal with JSONs?
EDIT:
Sorry for being extremely unclear. To clear things up, that's what I'm actually doing:
I'm using a generic function to call a DB procedure with whatever data that comes from the parameter
data
:public static IEnumerable<Dictionary<string, object>> CallDBProcedure(string proc, dynamic data) { using (NpgsqlConnection conn = new NpgsqlConnection(ConnStr)) { try { conn.Open(); using (var cmd = conn.CreateCommand()) { cmd.CommandText = proc; cmd.CommandType = System.Data.CommandType.StoredProcedure; foreach (string property in data.GetDynamicMemberNames()) { object propertyValue = data[property]; // The method convertNullValue returns the own value if it's not null // and returns DBNull.Value if it's null. Every value must be properly // converted, but I can't directly convert a DynamicJsonArray. cmd.Parameters.Add(new NpgsqlParameter(property, convertNullValue(propertyValue))); } var reader = cmd.ExecuteReader(); return new DrToDictionary().Serialize(reader); } } catch (Exception e) { throw e; } finally { conn.Close(); } } }
And then, in order to avoid exceptions, I'm processing
data
before I pass it toCallDBProcedure
, iterating over the DynamicJsonObject and converting every DynamicJsonArray inside it to a primitive array:public static void ProcessData(dynamic data) { // Directly using data.GetDynamicMemberNames() and modifiying data // inside the loop causes an exception. Using a string list instead (hacky code?). List<string> properties = ((Dictionary<string, object>.KeyCollection) data.GetDynamicMemberNames()).ToList(); foreach (string property in properties) { object propertyValue = data[property]; if (propertyValue != null && propertyValue.GetType() == typeof(DynamicJsonArray)) { Array arr = (Array)data[property]; if (arr.Length == 0) { // This works. data[property] = null; } else { // Discover the type of my array. if (arr.GetValue(0) is int) { // This works. data[property] = arr.Cast<Int32>().ToArray(); } else { // This doesn't. data[property] = arr.Cast<string>().ToArray(); } } } } }
For now I'm iterating over data
twice. I know that there must be an obvious and easy way to make this ugly code cleaner, but I'm just not seeing it.
EDIT2:
A solution that I found was to take only the string arrays and put them inside a different variable. Then I can use them normally. I really don't understand why dynamic objects can change their types in some cases and in other cases they can't.
EDIT3:
Forgot to mention that I'm receiving my json like this: dynamic data = System.Web.Helpers.Json.Decode(json);