In my test vb.net MVC web app, I have this json....
Public Class Person
Public Property Name As String
Public Property Age As Byte
Public Sub New(name As String, age As Byte)
Me.Name = name
Me.Age = age
End Sub
End Class
Function GetPerson() As JsonResult
Dim p As New Person("John Doe", 50)
Return Json(p, JsonRequestBehavior.AllowGet)
End Function
And in Monotouch I've got this...
JsonObject j;
Uri address = new Uri("http://mysite/home/GetPerson");
HttpWebRequest httpReq = (HttpWebRequest)HttpWebRequest.Create (address);
using (HttpWebResponse httpRes = (HttpWebResponse)httpReq.GetResponse ()) {
Stream s = httpRes.GetResponseStream ();
j = (JsonObject)JsonObject.Load (s);
}
And this class...
Public Class Person {
Public string Name { get; set; }
Public byte Age { get; set; }
}
How do I parse the JsonObject j into class of Person? .. I hoped for something like Person p = (Person)j.value;
Thanks!
Mojo
First, I would use int for Age. But assuming a JSON Structure like:
{
"Name" : "John Doe",
"Age" : 100,
}
If you wanted to use the baked in System.Json stuff:
var person = new Person()
var obj = JsonObject.Parse(json);
person.Name = obj["Name"].ToString();
person.Age = (int)obj["Age"];
I would HIGHLY recommend using ServiceStack.Text though, it's a highly optimized extremely fast library for consuming JSON with compatibility with both MonoTouch and Mono for Android...out of the box!
You can check out the the API for consuming JSON with ServiceStack here.
Even if this question is now old, here is the solution I use.
With MonoTouch, you can use .net Json serialization mechanism based on DataContract.
[DataContract]
Public Class Person {
[DataMember]
Public string Name { get; set; }
[DataMember]
Public byte Age { get; set; }
}
and use the DataContractJsonSerializer (found in System.Runtime.Serialization.Json)
Stream stream = httpRes.GetResponseStream ();
DataContractJsonSerializer jsSerializer = new DataContractJsonSerializer(typeof(Person));
Person person = (Person)jsSerializer.ReadObject(stream);
This way, the code is WCF compliant and work flawless on ms.net platform, mono and monotouch.
Related
So I am practising using newtonsoft.Json by creating a very simple Register.
In this code a user enters a first name and last name and this is put into my very simple Person object, which is then put into a List
The user can add multiple people and they are put into the List
My code isn't working and I need help because I am learning.
It isn't working because the serialization and deserialization process is coded wrong I think.
At the beginning of the code a List is declared with the People from the json file
List<Person> AllPeopleAdded = new List<Person>(JsonConvert.DeserializeObject<List<Person>>(File.ReadAllText(jsonfilePath)));
This is the code showing how the people are added to the json file
File.AppendAllText(jsonfilePath,JsonConvert.SerializeObject(PeopleAddedThisTime));
This is the full code
using System;
using System.Collections.Generic;
using System.IO;
using OOP__Data_Entry__homework.Classes.Person;
using Newtonsoft.Json;
namespace OOP__Data_Entry__homework
{
class Program
{
const string FirstNameText = "Enter A First Name";
const string LastNameText = "Enter A Last Name";
const string ContinueText = "Would you Like to Add Another Person, Yes or No";
const string YesResponse = "Yes";
const string NoResponse = "No";
const string ContinueErrorText = "Enter Yes or No";
const string jsonfilePath = #"C:\OOP- Data Entry- homework\PeopleSaved.json";
static void Main(string[] args)
{
//done so that line 29 can work, without swaure brackets there is no list for the List (AllPeopleAdded) to take in
if(File.Exists(jsonfilePath))
{
}
else
{
File.WriteAllText(jsonfilePath,"[]");
}
List<Person> AllPeopleAdded = new List<Person>(JsonConvert.DeserializeObject<List<Person>>(File.ReadAllText(jsonfilePath)));
List<Person> PeopleAddedThisTime = new List<Person>();
//done so that the jsonfile(PeopleSaved.json) doesnt error after the new People are added when the user says they do not want to add any more people (line 57)
if(File.ReadAllText(jsonfilePath).StartsWith("[]"))
{
File.WriteAllText(jsonfilePath,"");
}
string FirstName;
string LastName;
while(true)
{
System.Console.WriteLine(FirstNameText);
FirstName=Console.ReadLine();
System.Console.WriteLine(LastNameText);
LastName = Console.ReadLine();
Person newPerson = new Person(FirstName,LastName);
PeopleAddedThisTime.Add(newPerson);
System.Console.WriteLine(ContinueText);
while(true)
{
string response = Console.ReadLine();
if (response==YesResponse)
{
break;
}
else if (response == NoResponse)
{
File.AppendAllText(jsonfilePath,JsonConvert.SerializeObject(PeopleAddedThisTime));
foreach(Person allPersons in AllPeopleAdded)
{
System.Console.WriteLine($"\n {allPersons.GetFullName()}");
}
foreach(Person newPersons in PeopleAddedThisTime)
{
System.Console.WriteLine($"\n {newPersons.GetFullName()}");
}
return;
}
else
{
System.Console.WriteLine(ContinueErrorText);
}
}
}
}
}
}
This is the json file after the code is run once
[{"mFirstName":"john ","mLastName":"doe"},{"mFirstName":"Josh","mLastName":"Smith"}]
This is the json file after the code is run again
(It is formatted wrong-that is a problem)
[{"mFirstName":"john ","mLastName":"doe"},{"mFirstName":"Josh","mLastName":"Smith"}][{"mFirstName":"Serge","mLastName":"Superhero"}]
The Person Class
using System;
namespace OOP__Data_Entry__homework.Classes.Person
{
class Person
{
public string mFirstName {get; private set; }
public string mLastName {get; private set; }
public Person(string firstName, string lastName)
{
mFirstName = firstName;
mLastName = lastName;
}
public string GetFullName()
{
return mFirstName+" "+mLastName;
}
}
}
What the json file looks after a couple times the code is run using serge's code
[{"mFirstName":null,"mLastName":null},{"mFirstName":null,"mLastName":null},{"mFirstName":"f","mLastName":"f"}]
You have to deserialize existing json into list, add new person to existing users lists ( or maybe remove some) and after this to serialize the whole list again. Using append will never work, since json always must have only one root element, and you have to insert a new data inside of this root. But you are trying to add the second root and that makes json invalid.
string json = string.Empty;
using (StreamReader r = new StreamReader(jsonfilePath))
json = r.ReadToEnd();
List<Person> AllPeopleAdded = JsonConvert.DeserializeObject<List<Person>>(json);
List<Person> PeopleAddedThisTime = new List<Person>();
//.....
AllPeopleAdded.AddRange(PeopleAddedThisTime);
using (StreamWriter file = File.CreateText(jsonfilePath))
{
JsonSerializer serializer = new JsonSerializer();
serializer.Serialize(file, AllPeopleAdded);
}
// or serialize JSON to a string and then write string to a file
File.WriteAllText(jsonfilePath, JsonConvert.SerializeObject(AllPeopleAdded));
and fix person class
public class Person
{
public string mFirstName { get; private set; }
public string mLastName { get; private set; }
[JsonConstructor]
public Person(string mFirstName, string mLastName)
{
this.mFirstName = mFirstName;
this.mLastName = mLastName;
}
public string GetFullName()
{
return mFirstName + " " + mLastName;
}
}
I get the error below... Something is very wrong :( any ideas? (This is in a Windows Phone 8 app)
An exception of type 'Newtonsoft.Json.JsonReaderException' occurred in Newtonsoft.Json.DLL but was not handled in user code
And the code is
string responseBody = #" {""HighScoreId"":1,""Name"":""Debra Garcia"",""Score"":2.23},{""HighScoreId"":2,""Name"":""Thorsten Weinrich"",""Score"":2.65}";
GlobalHighScore s = JsonConvert.DeserializeObject<GlobalHighScore>(responseBody);
and the class is
public class GlobalHighScore
{
public int HighScoreId { get; set; }
public string Name { get; set; }
public double Score { get; set; }
}
Your JSON has more than one object, and neither are in an array. You either need to remove one of the objects from the JSON or add them to an array and deserialize them properly:
string responseBody =
#"[
{""HighScoreId"":1,""Name"":""Debra Garcia"",""Score"":2.23},
{""HighScoreId"":2,""Name"":""Thorsten Weinrich"",""Score"":2.65}
]";
var highScores =
JsonConvert.DeserializeObject<List<GlobalHighScore>>(responseBody);
I am not getting any root value of the Json Format.
I am getting the response as follows:
[{"Username":"demo","UserID":8,"Password":"demo","EmaiID":"demo#gmail.com"}]
I would like to have the format as follows
{UserList: [[{"Username":"demo","UserID":8,"Password":"demo","EmaiID":"demo#gmail.com"}]}
Service Declaration :
public interface IDemo
{
[OperationContract]
[WebInvoke(RequestFormat = WebMessageFormat.Json,ResponseFormat =
WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare,
UriTemplate = "/Validate", Method = "POST")]
Stream ValidateUser(Login obj);
}
[DataContract]
public class Login
{
public Login()
{
}
[DataMember]
public string Username { get; set; }
[DataMember]
public string Password { get; set; }
}
Service Definition :
public class Demo: IDemo
{
string Json = string.Empty;
JavaScriptSerializer obj1 = new JavaScriptSerializer();
public Stream ValidateUser(Login obj)
{
UserList objUserList = new UserList();
Users objUser = new Users();
objUser.Username = obj.Username;
objUser.Password = obj.Password;
objUserList = LoginDataService.ValidateUser(objUser.Username,objUser.Password) ;
if (objUserList.Count > 0)
{
Json = obj1.Serialize(objUserList);
WebOperationContext.Current.OutgoingResponse.ContentType =
"application/json; charset=utf-8";
}
else
{
UserError objError = new UserError();
objError.ErrMsg = "LoginFailed";objError.Username = objUser.Username ;
Json = obj1.Serialize(objError);
WebOperationContext.Current.OutgoingResponse.ContentType =
"application/json; charset=utf-8";
}
return new MemoryStream(Encoding.UTF8.GetBytes(Json));
}
}
Can anyone help me to get the result with root element and let me know what kind of mistake i have done.
Thanks & Regards,
Vijay
You are getting the format like that since you are serializing a collection into JSON. You can return a class that wraps the list inside as a property then you will get what you desire.
For ex. you can create a class like this
public class UserListResponse
{
public UserList UserList{get; set;}
}
Now you get the JSON as what you expected, like
{UserList:[..]}
I don't understand why you are returning a Stream and doing yourself all the serialization framework, basically this all done by the framework. All you have to do is return the wrapper class UserListResponse from the service method.
public class Demo: IDemo
{
public UserListResponse ValidateUser(Login obj)
{
...
return new UserListResponse{ UserList = objUserList};
}
}
The WCF will take care of returning the structure into JSON or XML and you don't need to worry about that.
While the above solution perfectly works you can also try using paramter BodyStyle=WebMessageBodyStyle.WrappedResponse of WebInvoke attribute on your method.
This wraps the values in type name.
I have a class as below
public class Person
{
public string Name { get; set; }
[DisplayName ("Please Enter Your Age")]
public int Age { get; set; }
public string Sex { get; set; }
}
I serialized this object to Json using json() of MVC3, but the DisplayName attribute is ignored. I get the json as
"*{"Name":"Person Name","**Age**":28,"Sex":"Male"}*"
Actually i was expecting
"*{"Name":"Person Name","**Please Enter Your Age**":28,"Sex":"Male"}*"
Code converts the object to json
[HttpGet]
public JsonResult JsonTest()
{
Person person = new Person();
person.Age = 28;
person.Name = "Person Name";
person.Sex = "Male";
return (Json(person, JsonRequestBehavior.AllowGet));
}
Any help would be appreciated!!!
You can use the DataContractJsonSerializer to give different names to your properties by using the [DataMember(Name = "myOwnName")] data annotation. Or write your own serializer.
Example can be found here.
Internally the Json method uses the JavaScriptSerializer class to serialize the class into a JSON string. It doesn't allow you to change property names. I guess you will have to roll your own JSON serialization routine. The question is: why do you need that?
I am looking at trying to use a Linq query to determine if the following JSON is true if it contains a product that has a SKU of 12345 OR a TypeCode of "C".
"[{\"SKU\":\"12345\",\"Description\":\"Test Part 12345\",\"TypeCode\":\"A\",\"Cost\":24.99},{\"SKU\":\"54567\",\"Description\":\"Test Part 54567\",\"TypeCode\":\"B\",\"Cost\":9.99},{\"SKU\":\"QWZ2342\",\"Description\":\"Test Part QWZ2342\",\"TypeCode\":\"C\",\"Cost\":19.99}]"
I have been working with the Json.net (http://james.newtonking.com/projects/json-net.aspx)
At first, you have to deserialize the JSON into a C# object, lets say Product.
class Product
{
public int SKU { get; set; }
public string Desc { get; set; }
public string TypeCode { get; set; }
public decimal Cost { get; set; }
}
then, using .NET's JavaScriptSerializer (System.Web.Script.Serialization), convert the json string to become List of your custom objects.
string json = "[{\"SKU\":\"12345\",\"Description\":\"Test Part 12345\",\"TypeCode\":\"A\",\"Cost\":24.99},{\"SKU\":\"54567\",\"Description\":\"Test Part 54567\",\"TypeCode\":\"B\",\"Cost\":9.99},{\"SKU\":\"QWZ2342\",\"Description\":\"Test Part QWZ2342\",\"TypeCode\":\"C\",\"Cost\":19.99}]"
JavaScriptSerializer jsonSerializer = new JavaScriptSerializer();
List<Product> productList = new List<Product>();
productList = jsonSerializer.Deserialize<List<Product>>(json);
the last step, using simple linq query, you cant check whether your product exist on the list:
var Found = from o in productList
where o.SKU == 12345
select o.SKU;
if (Found.Count() > 0)
return true;
else
return false;