I want to store the results from JSON in properties, but I don't know how. I'm using ASP.NET with MVC 4/Razor.
My model's constructor is:
public UserModel()
{
WebClient request = new WebClient();
string response = request.DownloadString(url);
JObject _naturalUserObject = (JObject)JsonConvert.DeserializeObject(response);
}
And I have the follow properties:
[Key]
public int Id { get; set; }
public int DisplayName { get; set; }
public int Avatar { get; set; }
To access a simple value from my JSON:
_naturalUserObject["users"][0]["name"];
The final question is: how can I store each value from my JObject in my model's properties and finally display it into my view?
Thanks in advance.
/EDIT/
My model now is:
public UserModel()
{
WebClient request = new WebClient();
string response = request.DownloadString(String.Format("http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key={0}&steamids={1}", ConfigurationManager.AppSettings["SteamApiKey"].ToString(), HttpContext.Current.Request.Cookies["SteamIdCookie"].Value));
string _naturalUserObject = JsonConvert.DeserializeObject<string>(response);
}
And one of my property is:
private string _avatar;
public string Avatar
{
get { return _avatar; }
set { _avatar = _naturalUserObject["response"]["players"][0]["avatar"]; }
}
But without success. =(
Lets say you have the following Json
string yourJsonString = "{\"FIRST_NAME\":\"Foo\",\"LAST_NAME\":\"Bar\"}";
You could model this Json as:
public class JsonModel
{
[JsonProperty("FIRST_NAME")]
public string FirstName {get; set;}
[JsonProperty("LAST_NAME")]
public string LastName {get; set;}
}
Note that you can use JsonPropertyAttribute to tell Json.Net what the property's corresponding json field is.
Now, that you have your model set up, can use JsonConvert.DeserializeObject<T>(...) to get a strongly typed instance of your json model.
JsonModel jsonModel = JsonConvert.DeserializeObject<JsonModel>(yourJsonString);
string firstName = jsonModel.FirstName; // Foo
string lastName = jsonModel.LastName; // Bar
As someone had mentioned, if you do it this way, you won't have to deal with JObject and moreover, it will force you to actually understand the structure of the json being returned.
Specifically in your example, you could store an object of type JsonModel and in your model's constructor initialize it using JsonConvert.DeserializeObject<T>. Your public properties could then just call into that JsonModel instance and get the appropriate values.
Here's a more detailed example. Assume you are getting back the json I had provided above and are using the same model we created before. Let's say you have a private field in your class of type JsonModel
private JsonModel jsonModel;
You can initialize it in your constructor:
public UserModel()
{
WebClient request = new WebClient();
string response = request.DownloadString(url);
jsonModel = JsonConvert.DeserializeObject<JsonModel>(response);
}
Now, your public properties can simply call into this JsonModel object.
public string FirstName
{
get { return jsonModel.FirstName; }
set { jsonModel.FirstName = value; }
}
I recommend ServiceStack.Text (available as a standalone NuGet package install, without the rest of the framework if you don't need it).
This adds two nice extension methods:
public class MyPOCO
{
public string Name {get; set; }
public int Age {get; set; }
}
And later:
string json = myPocoInstance.ToJson();
and:
MyPOCO instance = jsonString.FromJson<MyPOCO>();
Very fast too!
If you use Json.net you can deserialize directly into a clr object (which could be your viewmodel or model), you won't have to deal with JObject.
JsonConvert.DeserializeObject<myviewmodelormodel>(myjsondata);
If you get the object back as a string in JSON format. You can use the JSON de-serializer like this:
Put this into a static class this will become an extension method to all strings
public static T Deserialize<T>(this string json)
{
var obj = Activator.CreateInstance<T>();
using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(json)))
{
var serializer = new DataContractJsonSerializer(obj.GetType());
obj = (T) serializer.ReadObject(ms);
}
return obj;
}
EX:
this calls a url getting the result set in a string, then calls the
extension method to return an object.
the url returns MyPOCO
var stringValue = HttpGet(url);//how you get the value from a web service call
var myUserModel = stringValue.Deserialize<MyPOCO>();
Related
I am returning a json string to a WebMethod in WebForms and I want to take the json string and parse it into custom Order objects.
I have a class:
public class Order
{
public string Item { get; set; }
public string Color { get; set; }
public string Qty { get; set; }
public string Size { get; set; }
}
And a WebMethod:
[WebMethod]
public static string SendOrder(string json)
{
List<Order> orders = new List<Order>();
return json;
}
I am passing this string:
{
json: [
{
"Item":"Nike Polo #286772 - Women's Dri-FIT Micro Pique Short Sleeved Polo",
"Size":"XL",
"Color":"Light Blue",
"Quantity":"3"
},
{
"Item":"Port Authority Women's Jacket #L790 - Black",
"Size":"Medium",
"Color":"Black",
"Quantity":"3"
}
]
}
I want to loop through this string and creating new Orders.
What is the best way to do this?
That JSON is a little oddly formatted as it maps to the following classes (using http://json2csharp.com):
public class Json
{
public string Item { get; set; }
public string Size { get; set; }
public string Color { get; set; }
public string Quantity { get; set; }
}
public class RootObject
{
public List<Json> json { get; set; }
}
I'm not sure why you have a top-level variable named json, but whatever.
At this point just use JSON.NET to deserialize into the structure.
JsonConvert.DeserializeObject<RootObject>(yourJsonString);
If you want to rename the object from Json to Order you'll need to use an attribute for that. I don't recall the name off the top of my head but it should be easy to find in the JSON.NET documentation.
I recently completed a Windows Phone app that retrieved info from a Web API-based server as Json strings. I ended up using the JsonConvert class to convert my lists of objects from Json strings to my custom objects. Here's an example of one of my client-side methods that receives and converts the Json strings:
public async void GetGames()
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("base url");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.GetAsync("specific url extention (like api/Order)");
if (response.IsSuccessStatusCode)
{
string s = await response.Content.ReadAsStringAsync();
var deserializedResponse = JsonConvert.DeserializeObject<List<Order>>(s);
//rest of code
}
}
}
Also, make sure that your web method is actually doing something. The example web method you posted creates creates a new list then just returns the parameter you passed in. Using Web API, you could return a list of all Order objects in your database via a method similar to the following:
public IQueryable<Order> GetOrders()
{
return db.Orders; //db is an instance of your DbContext class
}
I hope this is helpful. Let me know if you have any questions.
I have a web api which accepts a class as argument (MyClass). In which a property is of type list. How shall i pass the argument so that the web api receives a list in that property field.
When i pass Id=1&Name=ABC&MyList=[{AnotherClassName : "The Name"}] in the POST body using REST client, i am getting the values only in Id and Name field. How shall i send the params in POST body, so that i receives a List of "AnotherClass" in the "MyList"
public class MyClass
{
public int Id { get; set; }
public string Name { get; set; }
public List<AnotherClass> MyList { get; set; }
}
public class AnotherClass
{
public int AnotherClassName { get; set; }
}
Thanks
You need to pass the JSON like this
{"Id":1,"Name":"abc","MyList":[{"AnotherClassName":1}]}
actually you mase a mistake in MyList object. The property AnotherClassName data type is int and you are passing it to string value and also enclose are your JSON to braces {....}.
The better way you should use NewtonSoft.JSON to convert your object to json before sending.
MyClass mc = new MyClass();
mc.Id = 1;
mc.Name = "abc";
List<AnotherClass> acl = new List<AnotherClass>();
acl.Add(new AnotherClass { AnotherClassName = 1 });
mc.MyList = acl;
var serializedData = JsonConvert.SerializeObject(mc);
I'm writing a .NET library (using Newtonsoft) that interacts with a REST service, and I have a service that's returning json, but the json id field is called '$id'. So I can't just create a corresponding $id property in my C# data class. I tried to use something like
[JsonObject(MemberSerialization.OptOut)]
public class DocData
{
[JsonProperty("$id")]
public string id { get; set; }
public string Name { get; set; }
}
but while Name gets assigned, the id property does not. Anyone know how to map this json key to .NET?
Thanks
It looks like this is a bug in JSON.NET, and I think you should report it. It works fine in LINQPad for any property name except $id.
void Main()
{
var s = JsonConvert.SerializeObject(new DocData{id = "hi", Name = "world"}).Dump();
JsonConvert.DeserializeObject<DocData>(s).Dump();
}
public class DocData
{
// [JsonProperty("i$d")] // this would work
// [JsonProperty("_id")] // as would this
// [JsonProperty("$name")] // and even this
[JsonProperty("$id")] // but this fails
public string id { get; set; }
public string Name { get; set; }
}
Evidently Json.NET uses $id as a reserved word to help it deal with object references.
var dd = new DocData{id = "hi", Name = "world"};
JsonConvert.SerializeObject(new[]{dd, dd}, new JsonSerializerSettings{PreserveReferencesHandling = PreserveReferencesHandling.Objects}).Dump();
// Output: [{"$id":"1","$id":"hi","Name":"world"},{"$ref":"1"}]
Still, it seems like it should let you capture the $id property if you're not using reference handling.
As a workaround, you can parse it into a JObject, and pull the property out directly:
var id = JObject.Parse(s)["$id"];
var obj = JsonConvert.DeserializeObject<DocData>(s);
obj.id = id;
I am getting this error when using my class.
Error
Expecting element 'root' from namespace ''.. Encountered 'None' with
name '', namespace
My Class
[DataContract]
public class EntryData
{
[DataMember]
public string EntryId { get; set; }
[DataMember]
public string EmailAddress { get; set; }
[DataMember]
public string StatusCode { get; set; }
[DataMember]
public string TotalVoteCount { get; set; }
public static T Deserialise<T>(string json)
{
var obj = Activator.CreateInstance<T>();
using (var memoryStream = new MemoryStream(Encoding.Unicode.GetBytes(json)))
{
memoryStream.Position = 0;
var serializer = new DataContractJsonSerializer(obj.GetType());
obj = (T)serializer.ReadObject(memoryStream); // getting exception here
return obj;
}
}
}
USAGE
string responseJson = new StreamReader(HttpContext.Current.Request.InputStream).ReadToEnd();
var results = EntryData.Deserialise<EntryData>(response)
I have seen online that it has to do with the memoryStream position BUT as you can see i am setting it to the beginning.
Please help.
Json going to handler
I don't set StatusCode or TotalVoteCount when passing JSON in. I don't think this is the problem though.
{
"EntryId":"43",
"EmailAddress":"test#email.com"
}
ANSWER
Instead of using Deserialize method in my class I am using now this.
//commented out this code.
string responseJson = new StreamReader(HttpContext.Current.Request.InputStream).ReadToEnd();
var results = EntryData.Deserialise<EntryData>(response)
// this is the way to go using JavaScriptSerializer
var serializer = new JavaScriptSerializer();
var results = serializer.Deserialize<EntryData>(response);
Could it be caused by your JSON names not matching your property names in C#?
My understanding is that
{
"FirstName" : "Mark"
}
Would be able to deserialize into:
[DataContract]
public class Person
{
[DataMember]
public string FirstName {get; set;}
}
but this wouldn't be able to serialize
{
"Name" : "Mark"
}
unless you changed your C# class to have an explicit name for the DataMember
[DataContract]
public class Person
{
[DataMember(Name="Name")]
public string FirstName {get; set;}
}
I'm not sure which error this would cause though. I Don't have enough first hand experience.
Do you think it could be an encoding problem? Have you tried using Encoding.UTF8 instead of Unicode?
All the examples I have seen using DataContractSerializer have used a UTF-8 encoding.
Encoding.Unicode is a UTF-16 encoding.
I can't find any documentation explicitly stating which encodings DataContractSerializer supports. I assume it would be smart enough to detect the proper encoding, but I don't know a whole whole lot about encodings. Maybe that isn't really possible in this instance.
I have the following Json string that I need to deserialize.
{"123456789":
{"short_description":"Delivered",
"detail_description":"Your item has been delivered"
}
}
The first field "123456789" is an id number, so basically this value can be different depending on the data being queried.
I'm using C# in visual studio. Obviously because the value of the first field can change I can't use a predefined class to deserialize the JSON into because this field will be used as the class name but the field value won't match the class name.
Is there a way to deserialize this into some sort of dynamic class but still access the fields as if it was a predefined class?
Alternatively is there a way to deserialize this into a predefined class even thought the class name doesn't match?
The service providing this data is a third party one so i don't have any control over it.
Here is one way which I use in production code. It might not be perfect, but it gets the job done.
using using System.Web.Script.Serialization;
// .....
public object GetJson(string url)
{
var json = Get(url); // I have code that makes this work, it gets a JSON string
try
{
var deserializer = new JavaScriptSerializer();
var result = deserializer.DeserializeObject(json);
return result;
}
catch (ArgumentException e)
{
// Error handling....
}
}
The object you receive back will be a generic Map, List, or whatever depending on the structure of the JSON. If you know what structure to expect, this is very useful without writing a customized parser or target object type.
You could then enumerate the keys of the Map, for example, to find your key that varies. A wrapper or conversion would then provide a consistent API to the rest of your application layer. Something like:
public class Order {
public string OrderNum { private set; get; }
public string ShortDesc { private set; get; }
public string Desc { private set; get; }
public static Order FromJson(object jsonResult)
{
var m = jsonResult as Map<string, object>;
// Handle errors, but I am not
var firstPair = m.First();
var detail = firstPair.Value as Map<string, object>;
var dummy = new Order()
{
OrderNum = firstPair.Key,
ShortDesc = detail["short_description"].ToString();
Desc = detail["detail_description"].ToString();
}
return dummy;
}
}
I liked answer above so I refactored it a bit. You'll need references to System.Web.Extensions.dll and System.Web.Script.Serialization.
Here's the class:
public class Order
{
public string OrderNum { private set; get; }
public string ShortDesc { private set; get; }
public string Desc { private set; get; }
public static Order FromJson(string jsonResult)
{
JavaScriptSerializer js = new JavaScriptSerializer();
// Should deserialize right to Dictionary<string, object>
// var result = ((Dictionary<string, object>)js.Deserialize<dynamic>(jsonResult)).First();
var result = js.Deserialize<Dictionary<string, object>>(jsonResult).First();
var detail = (Dictionary<string, object>)result.Value;
return new Order()
{
OrderNum = result.Key,
ShortDesc = detail["short_description"].ToString(),
Desc = detail["detail_description"].ToString()
};
}
}
And how to call it:
string json = "{\"123456789\": {\"short_description\":\"Delivered\", \"detail_description\":\"Your item has been delivered\" } }";
Order o = Order.FromJson(json);
You'll need to implement error handling on your own however.