3

I have the following:

public class BaseEntity<T> where T: class
{
    public OperationStatus OperationStatus { set; get; }
    public List<T> List { set; get; }

    protected internal BaseEntity()
    {
        if (OperationStatus == null)
        {
            OperationStatus = new OperationStatus();
            OperationStatus.IsSuccess = true;
        }

        this.List = new List<T>();
    }

    internal BaseEntity(IEnumerable<T> list)
    {
        if (OperationStatus == null)
        {
            OperationStatus = new OperationStatus();
            OperationStatus.IsSuccess = true;
        }

        this.List = new List<T>();
        foreach (T k in list)
        {
            this.List.Add(k);
        }
    }

}

public class KeyValuePair
{
    public string key;
    public string value;
}

public class KeyValuePairList : BaseEntity<KeyValuePair>
{
    public KeyValuePairList() { }
    public KeyValuePairList(IEnumerable<KeyValuePair> list)
        : base(list) { }
}

// Multiple other classes like KeyValuePair but all have the
// same behavior so they have been derived from BaseEntity

Now in my code, I am trying to map a JSON string to an instance of KeyValuePair list and I'm currently doing it as follows:

result = 
@"{
    \"d\": {
        \"OperationStatus\": {
            \"IsSuccess\": true,
            \"ErrorMessage\": null,
            \"ErrorCode\": null,
            \"InnerException\": null
        },
        \"List\": [{
            \"key\": \"Key1\",
            "\value\": \"Value1\"
        }, {
            \"key\": \"Key2\",
            \"value\": \"Value2\"
        }]
    }
}"

Attempt #1

JavaScriptSerializer serializer = new JavaScriptSerializer();
KeyValuePairList output = serializer.Deserialize<KeyValuePairList>(result);

However, this does not work because the constructor of KeyValuePairList is not being called with any arguments. If I remove that constructor, JSON serialization fails with an error No parameterless constructor found. How can I tell KeyValuePairList to use KeyValuePair as the template in its invocation? Or maybe how can I adapt JSON serializer for this purpose?

Attempt #2

I tried JSON.net too, as follows:

var oo = JsonConvert.DeserializeObject<KeyValuePairList>(result);

Any suggestions on how to make this work?

2 Answers 2

2

Actually the solution is simpler than I thought it would be. The problem is that the server is returning the JSON string with the root node d. Because of this the deserializing fails because it doesn't know what to do with the root node d. This can be solved as follow:

Step 1: Add an additional class JSONWrapper that wraps incoming JSON strings:

public class JSONWrapper<T> where T:class
{
    public T d {set; get;}
}

Step 2: Deserialize using this new class instead

JavaScriptSerializer serializer = new JavaScriptSerializer();
var oo = serializer.Deserialize<JsonWrapper<KeyValuePairList>>(result);

Much more in-line with my whole logic so I don't have to make any major changes. Thanks to everyone else who helped me out with their valuable time.

Sign up to request clarification or add additional context in comments.

1 Comment

OK, your question, your solution. But it is too much code for me just to deserialize a simple json.
0

Try T[] instead of List<T>

You should have two properties as,

public T[] Items{
    get{
        return ItemList.ToArray();
    }
    set{
        ItemList.Clear();
        ItemList.AddRange(value);
    }
}

[ScriptIgnore]
public List<T> ItemList {get;set;}

Items as array will be serialized in JSON and you can use ItemList for your other operations.

1 Comment

Thank you. Some more clarity would be great. Because I was using List before, I could just use the Add method of the list. This modification will break the existing code (the part inside the constructor where I add elements to the list). Any workaround for that?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.