Reputation: 116990
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?
Upvotes: 3
Views: 2518
Reputation: 39956
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.
Upvotes: 0
Reputation: 116990
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.
Upvotes: 2