0

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 to CallDBProcedure, 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);

Pedro Corso
  • 557
  • 8
  • 22
  • Pedro, your question is not quite clear. What are you trying to achieve? What's wrong with DynamicJsonArray so you need to convert them into primitive array types? Why do you want to do it "in place"? How do you learn that particular JSON contains `prop4` and that it's actual type is "array of integers"? I think that without a "bigger picture" it would be very hard to answer your question. – SergGr May 18 '17 at 21:25
  • Pedro, For `[1,2,3,4,5]` or `["text1", "text2", "text3"]` try to cast for `Object[]` or `ArrayList` not `Array`. – Bhavik Jani May 23 '17 at 13:19
  • @BhavikJani Both `[1,2,3,4,5]` and `["text1", "text2", "text3"]` are coming as a `DynamicJsonArray`. Tried the convertions you suggested. When I cast to `Object[]`, the object still keep it's type as `DynamicJsonArray`. When I try to cast to `ArrayList`, C# tells me that it's not possible to convert a `DynamicJsonArray` to an `ArrayList`. – Pedro Corso May 23 '17 at 13:47

1 Answers1

0

It is just reading the json object which is returned from the API.

E.g

You can use

dynamic stuff = JsonConvert.DeserializeObject("{ 'prop1' : 'sometext', 'prop2': '123',
    'prop3': 'True'}");

string Prop1= stuff.First.Prop1;
string Prop2= stuff.First.Prop2;

or

// For that you will need to add reference to System.Web.Helpers
dynamic json = System.Web.Helpers.Json.Decode(@""{ 'prop1' : 'sometext', 'prop2': '123',
    'prop3': 'True'}"");
Console.WriteLine(json.prop1);

another similar quetion in Stackoverflow as below How can I parse JSON with C#?

Derek C.
  • 890
  • 8
  • 22
Satya
  • 53
  • 8