Question

I'm trying to deserialize this Json using Json.Net lib.:-

{
    "Employees": [
        {
            "Employee": {
                "Name": "AAA",
                "Info": [
                    {
                        "Signature": "aaa"
                    },
                    {
                        "Group": "AaA"
                    },
                    {
                        "E-mail": "aAa"
                    },
                    {
                        "Tfn home": "1234"
                    },
                    {
                        "Tfn mobile": "1324"
                    },
                    {
                        "Tfn work": "1234"
                    },
                    {
                        "Tfn pager": "1234"
                    }
                ]
            }
        },
        {
            "Employee": {
                "Name": "BBB",
                "Info": [
                    {
                        "Signature": "bbb"
                    },
                    {
                        "Group": "BbB"
                    },
                    {
                        "E-mail": "bBb"
                    },
                    {
                        "Tfn home": "1234"
                    },
                    {
                        "Tfn mobile": "1234"
                    },
                    {
                        "Tfn work": "1234"
                    },
                    {
                        "Tfn pager": "1234"
                    }
                ]
            }
        }
    ]
}

Into the following:-

public class Foo
{
    private ObservableCollection<Employee> _fooEmployees = new ObservableCollection<Employee>();
    public ObservableCollection<Employee> FooEmployees
    {
        get { return _fooEmployees; }
        set { _fooEmployees = value; }
    }
}
[JsonObject]
public class Employee
{
    [JsonProperty(PropertyName = "Name")]
    public string Name { get; set; }

    [JsonProperty(PropertyName = "Info")] 

    private ObservableCollection<Infomation> _infoList = new ObservableCollection<Infomation>();
    public ObservableCollection<Infomation> InfoList 
    { 
        get { return _infoList; }
        set
        {
            _infoList = value;
        }
    }
}
[JsonDictionary]
public abstract class Infomation
{
    [JsonProperty(PropertyName = "Signature")]
    public string Signature { get; set; }

    [JsonProperty(PropertyName = "Group")]
    public string Group { get; set; }

    [JsonProperty(PropertyName = "E-mail")]
    public string Email { get; set; }

    [JsonProperty(PropertyName = "Tfn home")]
    public string TfnHome { get; set; }

    [JsonProperty(PropertyName = "Tfn mobile")]
    public string TfnMobile { get; set; }

    [JsonProperty(PropertyName = "Tfn work")]
    public string TfnWork { get; set; }

    [JsonProperty(PropertyName = "Tfn pager")]
    public string TfnPager { get; set; }
}

Using the following line of code:-

var kol = JsonConvert.DeserializeObject<Foo>(json);

The problem is that Kol return FooEmployees with 0 Count.

Anyone who can direct me to why it is not working?

Was it helpful?

Solution

You're getting an empty collection because your classes don't match your JSON. I see at least two issues:

First, the outer JSON object has a property called Employees but the Foo class you are deserializing into has a property called FooEmployees. Since the names don't match, your FooEmployees collection will remain empty. Try adding a [JsonProperty("Employees")] attribute to the FooEmployees property like you did elsewhere in your code.

Second, the Employees collection in the JSON does not actually contain a collection of Employee objects as you have defined them in your classes. Instead, it contains a collection of objects that each have single property called Employee which contains an Employee instance. To fix this, you can do one of the following:

  1. change your JSON to eliminate the extra layer.
  2. define a wrapper class (e.g. EmployeeHolder) to represent the extra layer in the JSON, and make FooEmployees a collection of those.
  3. implement a JSON converter to abstract away the extra layer during deserialization. See Is there a way to deserialize my JSON without using a wrapper class for each item? for more details on this approach.

OTHER TIPS

I generally don't mix my DTOs (an example would be what JSON deserializes into: Foo) and view model classes (classes that contain ObservableCollections or implement INotifyPropertyChanged, etc. and bind to visual controls)

I would deserialize into a plain old class (one that doesn't use ObservableCollection) and then populate a view model class from there. For example:

public class Foo
{
    private List<Employee> _fooEmployees = new List<Employee>();
    public List<Employee> FooEmployees
    {
        get { return _fooEmployees; }
        set { _fooEmployees = value; }
    }
//...
}

public class ViewModel
{
   public ObservableCollection<Employee> FooEmployees {get;set;}
   //....
}
//...
   var dto = JsonConvert.DeserializeObject<Foo>(json);
   var vm = new ViewModel{FooEmployees = dto.Employees};

(or maybe do a "copy constructor")...

You are holding an ObservableCollection, but Information is an abstract class. How do you expect it to create an instance of Information?

Try removing the abstract keyword.

I wanted to deserialize all ICollections as ObservableCollections. I could solve it with a very simple custom contract resolver:

public class JsonObservableCollectionConverter : DefaultContractResolver
{
    public JsonObservableCollectionConverter(bool shareCache) : base(shareCache)
    {

    }

    public override JsonContract ResolveContract(Type type)
    {
        if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ICollection<>))
        {
            return ResolveContract(typeof(ObservableCollection<>).MakeGenericType(type.GetGenericArguments()));
        }
        return base.ResolveContract(type);
    }
}

var settings = new JsonSerializerSettings
{
    ContractResolver = new JsonObservableCollectionConverter(true),
};

var result = JsonConvert.DeserializeObject<IEnumerable<TResult>>(json, settings);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top