0

I have a list of objects in below json format. I would like to deserialize using below code. It is throwing unable to convert to object error. I have tried below three options, but didnt help. jsoninput is a IEnumerable<string>converted into json object using ToJson().

Error: {"Error converting value \"{\"id\":\"11ef2c75-9a6d-4cef-8163-94daad4f8397\",\"name\":\"bracing\",\"lastName\":\"male\",\"profilePictureUrl\":null,\"smallUrl\":null,\"thumbnailUrl\":null,\"country\":null,\"isInvalid\":false,\"userType\":0,\"profilePrivacy\":1,\"chatPrivacy\":1,\"callPrivacy\":0}\" to type 'Api.Models.UserInfo'. Path '[0]', line 1, position 271."}

var requests1 = JsonConvert.DeserializeObject<UsersInfo>(jsoninput);
var requests2 = JsonConvert.DeserializeObject<IEnumerable<UserInfo>>(jsoninput);
var requests3 = JsonConvert.DeserializeObject<List<UserInfo>>(jsoninput);

//Below are my classes,
public class UsersInfo

{
    public List<UserInfo> UserInfoList { get; set; }
    public UsersInfo()
    {
        UserInfoList = new List<UserInfo>();
    }
}

public class UserInfo
{
    public string Id { set; get; }
    public string Name { set; get; }
    public string LastName { set; get; }
    public string ProfilePictureUrl { set; get; }
    public string SmallUrl { set; get; }
    public string ThumbnailUrl { get; set; }
    public string Country { set; get; }
    public bool IsInvalid { set; get; }
}

Below is my json object,

["{\"id\":\"11ef2c75-9a6d-4cef-8163-94daad4f8397\",\"name\":\"bracing\",\"lastName\":\"male\",\"profilePictureUrl\":null,\"smallUrl\":null,\"thumbnailUrl\":null,\"country\":null,\"isInvalid\":false}","{\"id\":\"318c0885-2720-472c-ba9e-1d1e120bcf65\",\"name\":\"locomotives\",\"lastName\":\"riddles\",\"profilePictureUrl\":null,\"smallUrl\":null,\"thumbnailUrl\":null,\"country\":null,\"isInvalid\":false}"]

Looping through individual items in json input and if i deserialize it like below, it works fine. But i want to deserialize the list fully. Note: jsoninput was a IEnumerable<string> before i convert in json object.

foreach (var re in jsoninput)
{
    var request0 = JsonConvert.DeserializeObject<UserInfo>(re);
}
15
  • Please provide the exact error you're seeing. Commented Jun 16, 2020 at 15:23
  • 3
    But fundamentally your JSON doesn't represent a list of objects - it represents a list consisting of a single string, which itself contains a JSON object. Commented Jun 16, 2020 at 15:24
  • Where did you take jsonInput from? Escaped like this, it is not a valid json (hence, the error) Commented Jun 16, 2020 at 15:25
  • 1
    Well you'd start by deserializing it to a List<string>, because that's what your JSON appears to represent. You can then iterate over each string in the list and deserialize that to a UserInfo. Commented Jun 16, 2020 at 15:33
  • 1
    Do you have any evidence that this would be a performance bottleneck? If it would be, are you able to serialize to a more sensible format to start with? (A list of strings where each string is JSON is pretty unfortunate.) Commented Jun 16, 2020 at 15:35

1 Answer 1

2

Please look at this fiddle: https://dotnetfiddle.net/XpjuL4

This is the code:

using System;
using System.Collections.Generic;
using Newtonsoft.Json;

//Below are my classes,
public class UsersInfo 
{
    public List<UserInfo> UserInfoList { get; set; }
    public UsersInfo()
    {
        UserInfoList = new List<UserInfo>();
    }
}

public class UserInfo
{
    public string Id { set; get; }
    public string Name { set; get; }
    public string LastName { set; get; }
    public string ProfilePictureUrl { set; get; }
    public string SmallUrl { set; get; }
    public string ThumbnailUrl { get; set; }
    public string Country { set; get; }
    public bool IsInvalid { set; get; }
}

public class Program
{
    public static void Main()
    {
        Console.WriteLine("Hello World");
        Option1();
        Option2();
    }

    public static void Option1(){
        string json = @"{""UserInfoList"":[
            {""id"":""11ef2c75 - 9a6d - 4cef - 8163 - 94daad4f8397"",""name"":""bracing"",""lastName"":""male"",""profilePictureUrl"":null,""smallUrl"":null,""thumbnailUrl"":null,""country"":null,""isInvalid"":false},
            { ""id"":""318c0885-2720-472c-ba9e-1d1e120bcf65"",""name"":""locomotives"",""lastName"":""riddles"",""profilePictureUrl"":null,""smallUrl"":null,""thumbnailUrl"":null,""country"":null,""isInvalid"":false}
        ]}";
        var obj = JsonConvert.DeserializeObject<UsersInfo>(json);
        obj.UserInfoList.ForEach(e => Console.WriteLine(e.Id));
    }

    public static void Option2(){
    string json = @"[
            {""id"":""11ef2c75 - 9a6d - 4cef - 8163 - 94daad4f8397"",""name"":""bracing"",""lastName"":""male"",""profilePictureUrl"":null,""smallUrl"":null,""thumbnailUrl"":null,""country"":null,""isInvalid"":false},
            { ""id"":""318c0885-2720-472c-ba9e-1d1e120bcf65"",""name"":""locomotives"",""lastName"":""riddles"",""profilePictureUrl"":null,""smallUrl"":null,""thumbnailUrl"":null,""country"":null,""isInvalid"":false}
        ]";
        var obj = JsonConvert.DeserializeObject<List<UserInfo>>(json);
        obj.ForEach(e => Console.WriteLine(e.Id));
    }
}

Both work, and are basically very close to what you are doing. You can either serialize it as a list (based on your json, I think that's the closest to your use case, and that's Option 2).

However, put extra attention to the JSON. I had to re-parse your JSON to make it work (https://jsonformatter.org/json-parser is a nice website to do it). For the sake of explaining the example, in C#, @ means raw string, and in raw string, quotes are escaped with double quotes "".

I would expect that the business logic generating this JSON is not correct, if the JSON you pasted is the direct result from it.

EDIT Given the OP's comment:

Thanks Tu.ma for your thoughts. The other method returns IEnumerable which is nothing but Dictionary.Where(x => x.Value == null).Select(x => x.Key).ToHashSet(). The values in Dictionary are -> Key is String, Value is UserInfo object serialized. So, in that case i should deserialize one by one? If not, i should serialize entire list in one shot? Am i right? – Raj 12 hours ago

The problem is in the way you are generating the list of UsersInfo. The result from Dictionary<string,string>.Where(x => x.Value == null).Select(x => x.Key).ToHashSet() is a bunch of strings, not of objects, so you need to serialize them one by one.

If you are worried about the linearity of the approach, you could consider running through it in parallel. Of course, you need to judge if it fits your application.

var userInfoStrings = Dictionary<string,string>.Where(x => x.Value == null).Select(x => x.Key).ToHashSet();

var UserInfoList = userInfoStrings.AsParallel().Select (u => JsonConvert.DeserializeObject<UsersInfo>(u)).ToList();
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks Tu.ma for your thoughts. The other method returns IEnumerable<string> which is nothing but Dictionary<string,string>.Where(x => x.Value == null).Select(x => x.Key).ToHashSet(). The values in Dictionary<string,string> are -> Key is String, Value is UserInfo object serialized. So, in that case i should deserialize one by one? If not, i should serialize entire list in one shot? Am i right?
I see. The result from Dictionary<string,string>.Where(x => x.Value == null).Select(x => x.Key).ToHashSet() is a list of strings, not of Users. So you need to serialize one by one. Please see the update in the answer.
Thanks for the suggestions. Pretty much covered my expectation. Will consider AsParallel() method based on our app data and performance.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.