locked
Parsing JSON data Issue RRS feed

  • Question

  • User-1188570427 posted

    Hello,

    {"text":"TestallDay","description":null,"recurrenceRule":null,"id":238,"recurrenceException":null,"allDay":true,"startDate":"2020-07-07T05:00:00Z","endDate":"2020-07-08T05:00:00Z","resourceTypeId_52":[134],"resourceTypeId_49":[118,124]}

    I am using a dev express product. I am going to allow for the resource types to be a select box or a tag box.

    Above is how the JSON in data is passed to my control via formData.

    I use to use this code:

    /// <summary>
    /// Gets the selected event resources.
    /// </summary>
    /// <param name="values">The values from the json object</param>
    /// <returns>List of selected event resources</returns>
    public IList<int> GetSelectedEventResources(string values)
    {
        var keyValuePairs = JsonConvert.DeserializeObject<Dictionary<string, string>>(values);
    
        var selectedEventResources = new List<int>();
    
        foreach (var keyValuePair in keyValuePairs.Where(x => x.Key.Contains(GetResourceTypeFieldExpressionForManaged())))
        {
            if (keyValuePair.Value.Length > 0)
            {
                if (keyValuePair.Value != "0")
                {
                    selectedEventResources.Add(Convert.ToInt32(keyValuePair.Value));
                }
            }
        }
    
        return selectedEventResources;
    }

    But now I have this error after going from a select box to a tag box with the way the JSON is pushed out. The format is not a dictionary anymore.

    I cannot make a generic mapping object because the resources at the end are dynamic and there could be 3 or 4 or 10!

    How can I parse out the JSON to deserialize it into multiple list of Ints for the resources?

    Do you have a suggestion of how I can map the JSON from scheduler when it is a tag box to pull out the records.

    I've tried something like this:

    https://www.jsonutils.com/

    public class Example
    {
        public string text { get; set; }
        public object description { get; set; }
        public object recurrenceRule { get; set; }
        public int id { get; set; }
        public object recurrenceException { get; set; }
        public bool allDay { get; set; }
        public DateTime startDate { get; set; }
        public DateTime endDate { get; set; }
        public IList<int> resourceTypeId_52 { get; set; }
        public IList<int> resourceTypeId_49 { get; set; }
    }

    But the resources can be dynamic and there is no way to to know static Items to set to an object.

    Any ideas of how to parse out the JSON?

    Thursday, July 9, 2020 8:06 PM

Answers

  • User1686398519 posted

    Hi tvb2727,

    According to your needs,I made an example to parse the json string, please refer to it.

    • Because the number of resourceTypeId_X is uncertain, I suggest that you use Dictionary<string, object> in the model, so that you can store the name of resourceTypeId_X and the corresponding value.
    • You can get all resources from examplesource.resourceTypeId2.

    Model

        public class Example
        {
            public string text { get; set; }
            public object description { get; set; }
            public object recurrenceRule { get; set; }
            public int id { get; set; }
            public object recurrenceException { get; set; }
            public bool allDay { get; set; }
            public DateTime startDate { get; set; }
            public DateTime endDate { get; set; }
            public Dictionary<string, object> resourceTypeId2 { get; set; }
        }

    Controller

    public ActionResult Index()
    {
    var values = "{\"text\":\"TestallDay\",\"description\":null,\"recurrenceRule\":null,\"id\":238,\"recurrenceException\":null,\"allDay\":true,\"startDate\":\"2020-07-07T05:00:00Z\",\"endDate\":\"2020-07-08T05:00:00Z\",\"resourceTypeId_52\":[134],\"resourceTypeId_49\":[118,124,00,89,96]}";
    var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
    Dictionary<string, object> Obj =serializer.Deserialize<Dictionary<string, object>>(values);
    var keysArray = Obj.Keys.ToArray();
    var valuesArray = Obj.Values.ToArray();
    var examplesource=JsonConvert.DeserializeObject<Example>(values);
    examplesource.resourceTypeId2 = new Dictionary<string, object>();
    for (int i = 0; i < Obj.Count(); i++)
    {
    var type =valuesArray[i] == null ? "string" : valuesArray[i].GetType().Name;
    if (type == "ArrayList")
    {
    examplesource.resourceTypeId2.Add(keysArray[i], GetResources(valuesArray[i]));
    }
    }
    return View();
    }
    public IList<int> GetResources(object values)
    {
    var valueslist= values as ArrayList;
    List<int> resultlist=new List<int>();
    for(int i = 0; i < valueslist.Count; i++)
    {
    resultlist.Add(Int32.Parse(valueslist[i].ToString()));
    }
    return resultlist;
    }

    Here is the result.

    Best Regards,

    YihuiSun

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Friday, July 10, 2020 9:40 AM
  • User-1188570427 posted

    YihuiSun,

    Your post is what I used and it worked PERFECT!

    I had to make a few changes no only on obtaining the ids from the JSON, but then making the applying from the object to the JSON string serialize process to a List of Ints now.

    Thanks a ton!

    Here is my final code:

            public IList<int> GetSelectedEventResources(string values)
            {
                var selectedEventResources = new List<int>();
                var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
                Dictionary<string, object> obj = serializer.Deserialize<Dictionary<string, object>>(values);
                var keysArray = obj.Keys.ToArray();
                var valuesArray = obj.Values.ToArray();
                for (int i = 0; i < obj.Count(); i++)
                {
                    if (keysArray[i].StartsWith(GetResourceTypeFieldExpressionForManaged()))
                    {
                        var type = valuesArray[i] == null ? "string" : valuesArray[i].GetType().Name;
                        if (type == "ArrayList")
                        {
                            if (valuesArray[i] != null)
                            {
                                var list = GetResources(valuesArray[i]);
                                selectedEventResources.AddRange(list);
                            }
                        }
                        else
                        {
                            if (valuesArray[i] != null)
                            {
                                selectedEventResources.Add(int.Parse(valuesArray[i].ToString()));
                            }
                        }
                    }
                }
    
                return selectedEventResources;
            }
            /// <summary>
            /// Gets the resources.
            /// </summary>
            /// <param name="values">The values.</param>
            /// <returns>Resources</returns>
            private IList<int> GetResources(object values)
            {
                var valueslist = values as ArrayList;
    
                List<int> resultlist = new List<int>();
    
                for (int i = 0; i < valueslist.Count; i++)
                {
                    resultlist.Add(int.Parse(valueslist[i].ToString()));
                }
    
                return resultlist;
            }

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Saturday, July 11, 2020 10:17 PM

All replies

  • Thursday, July 9, 2020 8:12 PM
  • User-943250815 posted

    What about use Newtonsoft.Json

    protected void jsonTEST()
    {
        string MyJSonString = "{\"text\":\"TestallDay\",\"description\":null,\"recurrenceRule\":null,\"id\":238,\"recurrenceException\":null,\"allDay\":true,\"startDate\":\"2020-07-07T05:00:00Z\",\"endDate\":\"2020-07-08T05:00:00Z\"}";
        Newtonsoft.Json.Linq.JObject zJSONData = Newtonsoft.Json.JsonConvert.DeserializeObject(MyJSonString);
        foreach (System.Collections.Generic.KeyValuePair<string, Newtonsoft.Json.Linq.JToken> item in zJSONData)
        {
            string Key = item.Key;
            string Value = item.Value;
        }
    }
    

    Thursday, July 9, 2020 9:57 PM
  • User-1188570427 posted

    What about use Newtonsoft.Json

    protected void jsonTEST()
    {
        string MyJSonString = "{\"text\":\"TestallDay\",\"description\":null,\"recurrenceRule\":null,\"id\":238,\"recurrenceException\":null,\"allDay\":true,\"startDate\":\"2020-07-07T05:00:00Z\",\"endDate\":\"2020-07-08T05:00:00Z\"}";
        Newtonsoft.Json.Linq.JObject zJSONData = Newtonsoft.Json.JsonConvert.DeserializeObject(MyJSonString);
        foreach (System.Collections.Generic.KeyValuePair<string, Newtonsoft.Json.Linq.JToken> item in zJSONData)
        {
            string Key = item.Key;
            string Value = item.Value;
        }
    }

    Hello jzero,

    You forgot the ending resourceTypeId_X items.

    {"text":"TestallDay","description":null,"recurrenceRule":null,"id":238,"recurrenceException":null,"allDay":true,"startDate":"2020-07-07T05:00:00Z","endDate":"2020-07-08T05:00:00Z","resourceTypeId_52":[134],"resourceTypeId_49":[118,124]}
    ,"resourceTypeId_52":[134],"resourceTypeId_49":[118,124]}

    The Number can be any number. In this case there are 2, but there could be 10. So the json DeserializeObject method is blowing up now because it isn't a string, string anymore.

    Thursday, July 9, 2020 10:13 PM
  • User-943250815 posted

    No I did it intentionally, just to show the concept.
    As I understood you JSON string can be like your sample, or same without some fields, or it can have any other structure and fields.
    In sample you can get each key and value for whatever JSON string you have

    But, if you know "all possible" fields, you can try NewtonSoft.DeserializeAnonymous
    https://www.newtonsoft.com/json/help/html/DeserializeAnonymousType.htm

    Thursday, July 9, 2020 10:30 PM
  • User-1188570427 posted

    No I did it intentionally, just to show the concept.
    As I understood you JSON string can be like your sample, or same without some fields, or it can have any other structure and fields.
    In sample you can get each key and value for whatever JSON string you have

    But, if you know "all possible" fields, you can try NewtonSoft.DeserializeAnonymous
    https://www.newtonsoft.com/json/help/html/DeserializeAnonymousType.htm

    That is the problem: 

    All the fields are going to be the same except the ones with "resourceTypeId_X".

    Those will change based on how many resourceTypeIds the designer sets up.

    Before I moved to a "tag box" control, it was a normal string,string key value pair.

    Now it could still be a string, string key value pair, but then it could also be multiple values that are being sent back from a tag box:

    https://js.devexpress.com/Documentation/19_1/ApiReference/UI_Widgets/dxScheduler/Configuration/resources/#allowMultiple

    That is the tag box example from dev express controls that I'm trying to work with. 

    Friday, July 10, 2020 2:31 AM
  • User1686398519 posted

    Hi tvb2727,

    According to your needs,I made an example to parse the json string, please refer to it.

    • Because the number of resourceTypeId_X is uncertain, I suggest that you use Dictionary<string, object> in the model, so that you can store the name of resourceTypeId_X and the corresponding value.
    • You can get all resources from examplesource.resourceTypeId2.

    Model

        public class Example
        {
            public string text { get; set; }
            public object description { get; set; }
            public object recurrenceRule { get; set; }
            public int id { get; set; }
            public object recurrenceException { get; set; }
            public bool allDay { get; set; }
            public DateTime startDate { get; set; }
            public DateTime endDate { get; set; }
            public Dictionary<string, object> resourceTypeId2 { get; set; }
        }

    Controller

    public ActionResult Index()
    {
    var values = "{\"text\":\"TestallDay\",\"description\":null,\"recurrenceRule\":null,\"id\":238,\"recurrenceException\":null,\"allDay\":true,\"startDate\":\"2020-07-07T05:00:00Z\",\"endDate\":\"2020-07-08T05:00:00Z\",\"resourceTypeId_52\":[134],\"resourceTypeId_49\":[118,124,00,89,96]}";
    var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
    Dictionary<string, object> Obj =serializer.Deserialize<Dictionary<string, object>>(values);
    var keysArray = Obj.Keys.ToArray();
    var valuesArray = Obj.Values.ToArray();
    var examplesource=JsonConvert.DeserializeObject<Example>(values);
    examplesource.resourceTypeId2 = new Dictionary<string, object>();
    for (int i = 0; i < Obj.Count(); i++)
    {
    var type =valuesArray[i] == null ? "string" : valuesArray[i].GetType().Name;
    if (type == "ArrayList")
    {
    examplesource.resourceTypeId2.Add(keysArray[i], GetResources(valuesArray[i]));
    }
    }
    return View();
    }
    public IList<int> GetResources(object values)
    {
    var valueslist= values as ArrayList;
    List<int> resultlist=new List<int>();
    for(int i = 0; i < valueslist.Count; i++)
    {
    resultlist.Add(Int32.Parse(valueslist[i].ToString()));
    }
    return resultlist;
    }

    Here is the result.

    Best Regards,

    YihuiSun

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Friday, July 10, 2020 9:40 AM
  • User-1188570427 posted

    Hi tvb2727,

    According to your needs,I made an example to parse the json string, please refer to it.

    • Because the number of resourceTypeId_X is uncertain, I suggest that you use Dictionary<string, object> in the model, so that you can store the name of resourceTypeId_X and the corresponding value.
    • You can get all resources from examplesource.resourceTypeId2.

    Model

        public class Example
        {
            public string text { get; set; }
            public object description { get; set; }
            public object recurrenceRule { get; set; }
            public int id { get; set; }
            public object recurrenceException { get; set; }
            public bool allDay { get; set; }
            public DateTime startDate { get; set; }
            public DateTime endDate { get; set; }
            public Dictionary<string, object> resourceTypeId2 { get; set; }
        }

    Controller

    public ActionResult Index()
    {
    var values = "{\"text\":\"TestallDay\",\"description\":null,\"recurrenceRule\":null,\"id\":238,\"recurrenceException\":null,\"allDay\":true,\"startDate\":\"2020-07-07T05:00:00Z\",\"endDate\":\"2020-07-08T05:00:00Z\",\"resourceTypeId_52\":[134],\"resourceTypeId_49\":[118,124,00,89,96]}";
    var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
    Dictionary<string, object> Obj =serializer.Deserialize<Dictionary<string, object>>(values);
    var keysArray = Obj.Keys.ToArray();
    var valuesArray = Obj.Values.ToArray();
    var examplesource=JsonConvert.DeserializeObject<Example>(values);
    examplesource.resourceTypeId2 = new Dictionary<string, object>();
    for (int i = 0; i < Obj.Count(); i++)
    {
    var type =valuesArray[i] == null ? "string" : valuesArray[i].GetType().Name;
    if (type == "ArrayList")
    {
    examplesource.resourceTypeId2.Add(keysArray[i], GetResources(valuesArray[i]));
    }
    }
    return View();
    }
    public IList<int> GetResources(object values)
    {
    var valueslist= values as ArrayList;
    List<int> resultlist=new List<int>();
    for(int i = 0; i < valueslist.Count; i++)
    {
    resultlist.Add(Int32.Parse(valueslist[i].ToString()));
    }
    return resultlist;
    }

    Here is the result.

    Best Regards,

    YihuiSun

    Thank you for the example. I'll respond hopefully later today or tomorrow when I get back on this project!

    Friday, July 10, 2020 12:55 PM
  • User348806598 posted

    Hi,

    You can define a property of type Dictionary<string, int[]> and use JProperty from Newtonsoft and have the following code to parse the data-

    IEnumerable<JProperty> props = item.Properties().Where(p => p.Name.Contains("resourceTypeId"));
                foreach (var prop in props)
                {
                    List<int> arrayItems = new List<int>();
                    foreach (var arrItem in prop.Value)
                    {
                        arrayItems.Add((int)arrItem);
                    }
                    data.ResourceTypeIds.Add(prop.Name, arrayItems.ToArray());
                }

    Here is a blog post created for the same-

    http://growingtech.blogspot.com/2020/07/purse-dynamic-json-with-c.html

    Friday, July 10, 2020 2:19 PM
  • User-1188570427 posted

    YihuiSun,

    Your post is what I used and it worked PERFECT!

    I had to make a few changes no only on obtaining the ids from the JSON, but then making the applying from the object to the JSON string serialize process to a List of Ints now.

    Thanks a ton!

    Here is my final code:

            public IList<int> GetSelectedEventResources(string values)
            {
                var selectedEventResources = new List<int>();
                var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
                Dictionary<string, object> obj = serializer.Deserialize<Dictionary<string, object>>(values);
                var keysArray = obj.Keys.ToArray();
                var valuesArray = obj.Values.ToArray();
                for (int i = 0; i < obj.Count(); i++)
                {
                    if (keysArray[i].StartsWith(GetResourceTypeFieldExpressionForManaged()))
                    {
                        var type = valuesArray[i] == null ? "string" : valuesArray[i].GetType().Name;
                        if (type == "ArrayList")
                        {
                            if (valuesArray[i] != null)
                            {
                                var list = GetResources(valuesArray[i]);
                                selectedEventResources.AddRange(list);
                            }
                        }
                        else
                        {
                            if (valuesArray[i] != null)
                            {
                                selectedEventResources.Add(int.Parse(valuesArray[i].ToString()));
                            }
                        }
                    }
                }
    
                return selectedEventResources;
            }
            /// <summary>
            /// Gets the resources.
            /// </summary>
            /// <param name="values">The values.</param>
            /// <returns>Resources</returns>
            private IList<int> GetResources(object values)
            {
                var valueslist = values as ArrayList;
    
                List<int> resultlist = new List<int>();
    
                for (int i = 0; i < valueslist.Count; i++)
                {
                    resultlist.Add(int.Parse(valueslist[i].ToString()));
                }
    
                return resultlist;
            }

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Saturday, July 11, 2020 10:17 PM