Json Deserialization is not working with Flurl

六眼飞鱼酱① 提交于 2020-01-06 05:57:31

问题


I try to consume an json APIwith Flurl from a website and I'm getting parse errors or conversion errors. I'm not sure what is my problem since is the first time I deal with json files. I utilize the following online tool to create a C# object out of the json file. But when I try to get a response with Flurl I get the following errors.

System.AggregateException: One or more errors occurred. ---> Flurl.Http.FlurlParsingException: Response could not be deserialized to JSON: GET ---> Newtonsoft.Json.JsonSerializationException: Error converting value "{"Group":[{"name":"Senior","id":1},{"name":"Age","id":1}],"Area":[{"AreaID":58,"Description":"Years 2018-19","Week":1150,"taken":true,"LDate":null","Label":"RED"}]

Path '', line 1, position 4814377. ---> System.ArgumentException: Could not cast or convert from System.String to System.Collections.Generic.List`1[JsonTest.SeatTest].

This is the chunk of code that fails:

var response = await url.WithHeaders(new
    User_Agent = ConstantData.UserAgent,
    Accept = Accept,
    Referer = Referer})
    ..GetJsonAsync<List<SeatTest>>()
    .Result;

But now if I use the following:

var response = await url.WithHeaders(new
    User_Agent = ConstantData.UserAgent,
    Accept = Accept,
    Referer = Referer})
    .GetStringAsync()
    .Result;

I get (which I think is normal, not sure) the following string when I do a quick watch or hover over the response variable.

"\"{\\"Group\\":[{\\"name\\":\\"Senior\\",\\"id\\":1},{\\"name\\":\\"Age\\",\\"id\\":1}],\\"Area\\":[{\\"AreaID\\":58,\\"Description\\":\\"Years 2018-19\\",\\"Week\\":1150,\\"taken\\":true,\\"LDate\\":null",\\"Label\\":\\"RED\\"}]

If I apply the following:

var json = JsonConvert.DeserializeObject<SeatTest>(response);

it will also throw the exception that I already post.

OR

If I skip the above line and do the following:

var jSerial = new JavaScriptSerializer();
jSerial.MaxJsonLength = 50000000;
string jsonStr = jSerial.Deserialize<string>(response); 
var data = jSerial.Deserialize<SeatTest>(jsonStr);

My class objects appear null. But I don't get any errors or exceptions.

The that Flurl code that I'm using looks like follow, or at least the one I want to utilize:

 var response = url.WithHeaders(new
                {
                    User_Agent = ConstantData.UserAgent,
                    Accept = Accept,
                    Referer = Referer
                })
                    .GetJsonAsync<List<SeatTest>>()
                    .Result;

And my object model looks like:

public class SeatTest
    {
        [JsonProperty(PropertyName ="Group")]
        public List<Group> groups { get; set; }
        [JsonProperty(PropertyName = "Area")]
        public List<Group> areas { get; set; }
     }

 [Serializable]
    public class Group
    {
        public string name { get; set; }
        public int id { get; set; }

    }

 [Serializable]
 public class Area
    {
        public int AreaID{ get; set; }
        public string Description { get; set; }
        public int Week { get; set; }
        public bool Taken { get; set; }
        public DateTime LDate { get; set; }
        public string Label { get; set; }
    }

I expect an object that is filled with the data that comes from the API, but instead I get exceptions:

System.AggregateException: One or more errors occurred. ---> Flurl.Http.FlurlParsingException: Response could not be deserialized to JSON: GET ---> Newtonsoft.Json.JsonSerializationException: Error converting value "{"Group":[{"name":"Senior","id":1},{"name":"Age","id":1}],"Area":[{"AreaID":58,"Description":"Years 2018-19","Week":1150,"taken":true,"LDate":null","Label":"RED"}]

Path '', line 1, position 4814377. ---> System.ArgumentException: Could not cast or convert from System.String to System.Collections.Generic.List`1[JsonTest.SeatTest].

EDIT

var jSerial = new JavaScriptSerializer();
jSerial.MaxJsonLength = 50000000;
string jsonStr = jSerial.Deserialize<string>(response); 
/*First pass: Here I already got the info that I need, how I map it to my class?, since I would like to use Flurl GetAsync() and map it to my object and not a string */
/*Above line response val:  "\{\\\"Group\\\":[{\\\"name\\\":\\\"Senior\\\",\\\"id\\\":1},{\\\"name\\\":\\\"Age\\\",\\\"id\\\":2}],\\\"Area\\\":[{\\\"AreaID\\\":58,\\\"Description\\\":\\\"Season 2018-2019\\\",\\\"Week\\\":1150,\\\"taken\\\":true,\\\"LDate\\\":\\\"2019-07-07T00:00:00\\\",\\\"Label\\\":\\\"RED\\\"}]} */
/*Above line jsonStr val: null*/

var data = jSerial.Deserialize<SeatTest>(jsonStr);
/*Above line jsonStr val same as raw in postman:  "\{\"Group\":[{\"name\":\"Senior\",\"id\":1},{\"name\":\"Age\",\"id\":2}],\"Area\":[{\"AreaID\":58,\"Description\":\"Season 2018-2019\",\"Week\":1150,\"taken\":true,\"LDate\":\"2019-07-07T00:00:00\",\"Label\":\"RED\"}]} */
/* data value after above line: Group: null, Area: null*/

Raw Postman Json

{
   \"Group\": [
        {
            \"name\": \"Senior\",
            \"id\": 1
        },
        {
            \"name\": \"Adult\",
            \"id\": 2
        }
    ],
    \"Area\": [
        {
            \"AreaID\": 58,
            \"Description\": \"Area 2018-2019\",            
            \"Week\": 1150,
            \"taken\": true,
            \"LDate\": \"2019-07-07T00:00:00\",
            \"Label\": \"RED\"
        },
        {
            \"SeasonID\": 57,
            \"Description\": \"Area 51\",           
            \"Week\": 1,
            \"taken\": true,
            \"LDate\": \"2019-07-015T00:00:00\",
            \"Label\": \"GREEN\"
        }]
}

Json also how JsonStr (first pass) looks like in Quick watch

{
   "Group": [
        {
            "name": "Senior",
            "id": 1
        },
        {
            "name": "Adult",
            "id": 2
        }
    ],
    "Area": [
        {
            "AreaID": 58,
            "Description": "Area 2018-2019",            
            "Week": 1150,
            "taken": true,
            "LDate": "2019-07-07T00:00:00",
            "Label": "RED"
        },
        {
            "SeasonID": 57,
            "Description": "Area 51",           
            "Week": 1,
            "taken": true,
            "LDate": "2019-07-015T00:00:00",
            "Label": "GREEN"
        }]
}

回答1:


Let's look at the error message:

Path '', line 1, position 4814377. ---> System.ArgumentException: Could not cast or convert from System.String to System.Collections.Generic.List`1[JsonTest.SeatTest].

This is telling you that somewhere in the JSON response (at the 4,814,377th character to be exact), there's a string where in array is expected. It appears that you're expecting both "Group" and "Area" properties to be arrays in the JSON, but somewhere deep down in the response at least one of them is a string.

One way to work around this is to parse the response string to a JArray and build your strongly-typed list one by one, handling parsing errors along the way:

var results = new List<SeatTest>();

var arr = JArray.Parse(response);
foreach (var obj in arr) {
    try {
        var seat = obj.ToObject<SeatTest>();
        results.Add(seat);
    }
    catch (Exception ex) {
        // parsing error, inspect ex and obj.ToString(). log? ignore?
    }
}


来源:https://stackoverflow.com/questions/57223821/json-deserialization-is-not-working-with-flurl

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!