I'm attempting to deserialize json returned from javascript via Silverlight.
Basically on the client side I am returning JSON and in my C# handler, I am getting it via ScriptObject...
I tried the ConvertTo method on the ScriptObject and still could not get anything.
How would I be able to convert a ScriptObject into a C# object that is a list of objects?
SomeCallBack(ScriptObject result) {
// convert to managed object
var objects = result.ConvertTo<List<SomeObjectClass>>(); // can't get any property from it..
// however the count is correct...
MessageBox.Show("count: " + objects.Count); // shows correct count of items
}
Silverlight contains no API to take a ScriptObject and serialise to a JSON string.
Silverlight supports JSON serialisation via the System.Runtime.Serialization.Json.DataContractJsonSerializer class found in the System.ServiceModel.Web dll.
You will need to get some javascript base JSON serialiser to convert the value you are trying to pass as a ScriptObject so that you pass a JSON string parameter instead of a ScriptObject. I believe the popular tool for this job is JQuery.
Now it looks like you were expecting a set (JSON like "[x1,x2,,,xn]") where x items are of type SomeObjectClass. You can use this little generic function to deserialise such a list :-
List<T> DeserializeJSON<T>(string json)
{
byte[] array = Encoding.UTF8.GetBytes(json);
MemoryStream ms = new MemoryStream(array);
DataContractJsonSerializer dcs = new DataContractJsonSerializer(typeof(List<T>));
return (List<T>)dcs.ReadObject(ms);
}
You would do:-
var objects = DeserializeJSON<SomeObjectClass>(someJSON);
http://json.codexplex.com/
They have a silverlight version, sounds like the Newtonsoft.Json.Linq.JObject is what you're after.
If you are returning an actual JSON object, then you can actually use the ScriptObject.ConvertTo method to deserialize the JSON object directly into a C# object. For example, you could do:
JSON Object
{ id: 0001,
name: 'some_name',
data: [0.0, 1.0, 0.9, 90.0] }
C# Object
using System.Runtime.Serialization; // From the System.Runtime.Serialization assembly
[DataContract]
public struct JsonObj
{
[DataMember]
public int id;
[DataMember]
public string name;
[DataMember]
public double[] data;
}
C# Callback
public void SomeCallback(ScriptObject rawJsonObj)
{
// Convert the object
JsonObj jsonObj = rawJsonObj.ConvertTo<JsonObj>();
}
However, if you are returning a string that represents the JSON object, as opposed to an actual JSON object, then this will not work and you will have to use an alternate deserialization method. Refer to MSDN for more details.
Hope this helps.
I've got it working just by mimicking JS objects by C# code. Interestingly enough it even allowed for objects literals to be used on a JS side (see Collection items, they are just object literals - nice move - indeed JS is the driver!).
SL Code (I pass a JS object into my SL component for processing):
[ScriptableMember()]
public string GetValue(ScriptObject o)
{
Prototype p = (Prototype)o.ConvertTo<Prototype>();
return "A";
}
JS:
control.Content.ExternalName.GetValue({ Collection: [{ a: "A1" }, { a: "A2"}] })
C#
public class Prototype
{
public List<PrototypeItem> Collection
{
get;
set;
}
}
public class PrototypeItem
{
public string a
{
get;
set;
}
}
Related
I'm writing a WebApi that returns an object MyObject. The MyObject class is defined in another DLL which i cannot modify it's source. This MyObject class did not put setters/getters so the public members are not properties, they are just fields.
So in my WebApi code, i want to return this Json MyObject, but all i am getting in the http request is an empty {} json data, when i know for a fact the object does contain data. The only difference is it did not pub setters/getters, that why it is returning {} noting.
How can i return the MyObject back as Json with data without having to make my own MyOwnObject which all the exact fields but property set them as get/set properties?
For Example, if i use
public class MyObject
{
public string name;
}
this version returns empty {} data even if name contains something, where as
public class MyObject
{
public string name { get; set; }
}
will property return the Json data, but i am unable to modify MyObject because it is written from another DLL, which i dont have source.
Many thanks.
You can use Newtonsoft Json.Net (Open source, MIT licence), it will serialize public properties into a stringified JSON object. All you have to do is use the JsonConvert.SerializeObject static method.
However you'd have to do some extra work on your action, since you need to explicitly return a stringified object.
public HttpResponseMessage Get()
{
// initialize your MyObject instance
var cls = new MyObject
{
name = "AAAAA"
};
var stringified = JsonConvert.SerializeObject(cls);
var response = Request.CreateResponse(HttpStatusCode.OK);
// explicitly return a stringified JSON object
response.Content = new StringContent(stringified, Encoding.UTF8, "application/json");
return response;
}
More on this SO question
Don't expose that external object directly through your webapi.
keep all your models closer to your API code, where you can change when ever you need. (in your case, you need to create new class in your api project with same properties and gets and sets)
use automapper to map external object into your api model (it will make easier for you)
My JSON is as follows:
{"t":"1339886","a":true,"data":[],"Type":[['Ants','Biz','Tro']]}
I found the Newtonsoft JSON.NET deserialize library for C#. I tried to use it as follow:
object JsonDe = JsonConvert.DeserializeObject(Json);
How can I access to the JsonDe object to get all the "Type" Data? I tried it with a loop but it is not working because the object does not have an enumerator.
You can implement a class that holds the fields you have in your JSON
class MyData
{
public string t;
public bool a;
public object[] data;
public string[][] type;
}
and then use the generic version of DeserializeObject:
MyData tmp = JsonConvert.DeserializeObject<MyData>(json);
foreach (string typeStr in tmp.type[0])
{
// Do something with typeStr
}
Documentation: Serializing and Deserializing JSON
A much easier solution: Using a dynamic type
As of Json.NET 4.0 Release 1, there is native dynamic support.
You don't need to declare a class, just use dynamic :
dynamic jsonDe = JsonConvert.DeserializeObject(json);
All the fields will be available:
foreach (string typeStr in jsonDe.Type[0])
{
// Do something with typeStr
}
string t = jsonDe.t;
bool a = jsonDe.a;
object[] data = jsonDe.data;
string[][] type = jsonDe.Type;
With dynamic you don't need to create a specific class to hold your data.
As per the Newtonsoft Documentation you can also deserialize to an anonymous object like this:
var definition = new { Name = "" };
string json1 = #"{'Name':'James'}";
var customer1 = JsonConvert.DeserializeAnonymousType(json1, definition);
Console.WriteLine(customer1.Name);
// James
//Your snippet
object JsonDe = JsonConvert.DeserializeObject(Json);
//what you need to do
JObject JsonDe = JsonConvert.DeserializeObject<JObject>(Json);
Now you have and object with suitable properties and methods to work with the data.
You could also use Dictionary<string,object> instead of JObject. However, there are other alternatives, strongly-type though.
NewtonSoft.Json is an excellent library. I have used it for many use cases.
The beauty of json is that one can create schemas dynamically. Therefore we need to be able to write generic code to work with them
I'm trying to parse a JSON rpc 2.0 request. The standard is defined here.
I've defined my class as:
[DataContract]
public class JsonRpc2Request
{
public string method;
[DataMember(Name = "params")]
public object parameters;
public object id;
}
I then try and parse a request as follows:
JavaScriptSerializer ser = new JavaScriptSerializer();
var obj = ser.Deserialize<JsonRpc2Request>(Message.Trim());
obj.parameters is always null. I think this is because I can't define an object with the name params as per the JSON RPC spec. (My attempt is using the [DataMember(Name="params")] decoration.
How can I populate my parameters object when the JSON RPC spec calls for the name params which is a keyword in c#?
You can use the DataContractJsonSerializer:
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(JsonRpc2Request));
MemoryStream stream = new MemoryStream(Encoding.Unicode.GetBytes(Message.Trim()));
var obj = ser.ReadObject(stream);
and you'll want to annotate method and id with the DataMember attribute as well.
I would use Json.Net to get the full control over serialization/deserialization process
string json = #"{""method"":""mymethod"",""params"":[1,2],""id"":3}";
var rpcReq = JsonConvert.DeserializeObject<JsonRpc2Request>(json);
public class JsonRpc2Request
{
[JsonProperty("method")]
public string Method;
[JsonProperty("params")]
public object[] Parameters;
[JsonProperty("id")]
public string Id;
}
Since after completing this step, you are going to have to deal with more complex cases like
#"{""method"":""mymethod"",""params"":[{""name"":""joe""}],""id"":3}";
I have a JSON-string with a fixed number of arrays of different objects (created in Java with JSONObjects and JSONArrays):
[
[ //The first type of object
{
"Initials":"MUS"
},
{
"Initials":"NA"
}
],
[ //The second type
{
"ToolId":17
},
{
...
}
]
... //etc.
]
So I've created some Dummy-classes that has corresponding properties to the objects within the array, which works:
private class DummyEmployee
{
public string Initials { get; set; }
}
//etc.
But I can't figure out how the container class should be designed. This is how I did it:
private class DataContainer
{
public List<DummyEmployee> Employees { get; set; }
public List<DummySecondType> SecondTypes { get; set; }
//etc.
}
This is how I attempt to deserialize the JSON-data:
JavaScriptSerializer ser = new JavaScriptSerializer();
string jsonDataFromClient = ...;
DataContainer jsonData = ser.Deserialize<DataContainer>(jsonDataFromClient);
And it doesn't work. I get the following error while passing the data:
Type 'GUI.ValidateLoginData+DataContainer' is not supported for deserialization of an array.
I couldn't find any other subjects on the matter of deserializing arrays of different objects.
yes i will not work
notice that in your javascript object is basically an array and because javascript is a dynamic language there it is a valid array where as c# isnt so an array(or list) must contain objects of same kind. however if you still need to implement this and you have control over your JSON structure edit it to this
{
Employees:[ //The first type of object
{
"Initials":"MUS"
},
{
"Initials":"NA"
}
],
SecondTypes:[ //The second type
{
"ToolId":17
},
{
...
}
]
... //etc.
}
and your current c# object might map correctly.
and if you dont have control over the JSON structure then you have to use dynamic objects in c#
UPDATE:-for the case in which you dont have control over your JSON structure (or you dont wanna edit it).
try deserializing your JSON object to an array of dynamic type
UPDATE 2:- because you are curious try deserializing the existing JSON structure to an object of type List<List<dynamic>> and though i havent tried it but it should work fine.
one disadvantage of this solution however is that you wont be able to distinguish between two different types of objects namely Employee and SecondTypes
Use this online tool to create the C# classes for you. You can then fine tune the classes (Name, etc) as per you need. At least, you can get idea that the model classes that you are creating are correct or not.
JSON to C#
did you add [Serializable] attribute to your DataContainer?
am new to Json so a little green.
I have a Rest Based Service that returns a json string;
{"treeNode":[{"id":"U-2905","pid":"R","userId":"2905"},
{"id":"U-2905","pid":"R","userId":"2905"}]}
I have been playing with the Json.net and trying to Deserialize the string into Objects etc.
I wrote an extention method to help.
public static T DeserializeFromJSON<T>(this Stream jsonStream, Type objectType)
{
T result;
using (StreamReader reader = new StreamReader(jsonStream))
{
JsonSerializer serializer = new JsonSerializer();
try
{
result = (T)serializer.Deserialize(reader, objectType);
}
catch (Exception e)
{
throw;
}
}
return result;
}
I was expecting an array of treeNode[] objects. But its seems that I can only deserialize correctly if treeNode[] property of another object.
public class treeNode
{
public string id { get; set; }
public string pid { get; set; }
public string userId { get; set; }
}
I there a way to to just get an straight array from the deserialization ?
Cheers
You could use an anonymous class:
T DeserializeJson<T>(string s, T templateObj) {
return JsonConvert.Deserialize<T>(s);
}
and then in your code:
return DeserializeJson(jsonString, new { treeNode = new MyObject[0] }).treeNode;
Unfortunately JSON does not support Type Information while serializing, its pure Object Dictionary rather then full Class Data. You will have to write some sort of extension to extend behaviour of JSON serializer and deserializer in order to support proper type marshelling.
Giving root type will map the object graph correctly if the types expected are exact and not derived types.
For example if I have property as array of base class and my real value can contain derived child classes of any type. JSON does not support it completely but web service (SOAP) allows you to serialize objects with dynamic typing.