JsonConvert a json with a list<> element WP8 - windows-phone-8

I have a json coming from webservice, which has a List<> element in it.
But when I try to deserialize it using Newtonsoft.Json
Response resp = JsonConvert.DeserializeObject<Response>(responseStr);
then when I fetch the list using resp.ProjectList, it throws a null pointer exception.
So the List<Project> is not getting deserialized.
Any idea what am I missing?
The response is of the form:
public Response
{
public string msg;
public List<Project> ProjectList{get; set;}
}
[DataContract]
public class Project
{
[DataMember]
public string ID {get; set;}
}

Just remove the [DataContract] and [DataMember] attributes, they do not mix well with Json.NET.
Or you can do the deserialization "manually"
var j = JToken.Parse("{ \"Msg\": \"Success\", \"ProjectList\": [ { \"ID\": \"/Date(1400120100000-0700)/\" }, { \"ID\": \"/Date(1404260520000-0700)/\" } ] } ");
var resp = new Response
{
msg = j.SelectToken("Msg").ToString(),
ProjectList = ((JArray) j.SelectToken("ProjectList")).Select(l => new Project {ID = l.SelectToken("ID").ToString()}).ToList()
};

Related

Xamarin store multiple data in Variable

I have my code, where i fetch data from a url and parse that data with json.
public async void GetItems()
{
HttpResponseMessage response = new HttpResponseMessage();
HttpClient httpclient = new HttpClient();
Uri uri = new Uri("URL");
response = await httpclient.GetAsync(uri);
if (response.IsSuccessStatusCode)
{
var JsonContent = await response.Content.ReadAsStringAsync();
JArray jArray = JArray.Parse(JsonContent);
foreach (var data in jArray)
{
var latitude = data["latitude"];
Console.WriteLine(latitude);
}
}
}
in this code I get all my data and print them into the console.
I have a class with the variables i want to set
public class FetchedObjects
{
public string name { get; set; }
public double latitude { get; set; }
public double longitude { get; set; }
}
How can I store each data from my jArray into these variables? I want to have access to these from my ios or android project.
EDIT
I have some values in json, which are null. How can i handle these, while creating the list? My App crashes, it says :
Error setting value to 'valuename' on 'App.FetchedObjects'
Try it code:
List<FetchedObjects> list = jArray.ToObject<List<FetchedObjects>>();
Edit
in pcl library create class:
public class YourClass
{
public async Task<List<FetchedObjects>> GetItems()
{
....
if(jArray != null)
{
List<FetchedObjects> list = jArray.ToObject<List<FetchedObjects>>();
return list;
}
else
{
return null;
}
...
}
Add reference to pcl library in your ios and android projects and Use class YourClass

MVC 5 populate a model with Json

I have the following ActionResult:
public ActionResult WeatherWidget()
{
string json = string.Empty;
using (var client = new WebClient())
{
json = client.DownloadString("http://api.wunderground.com/api/xxxxxxxxx/geolookup/conditions/forecast/q/Australia/sydney.json");
}
WeatherWidget weatherWidget = new WeatherWidget()
{
//What do I put in here?
};
return View(weatherWidget);
}
And the following model:
public class WeatherWidget
{
public string city { get; set; }
public string lat { get; set; }
public string lon { get; set; }
}
Here is a snippet of the json:
{
"response": {
"version":"0.1",
"termsofService":"http://www.wunderground.com/weather/api/d/terms.html",
"features": {
"geolookup": 1
,
"conditions": 1
,
"forecast": 1
}
}
,"location": {
"type":"INTLCITY",
"country":"AU",
"country_iso3166":"AU",
"country_name":"Australia",
"state":"VC",
"city":"Falls Creek",
"tz_short":"AEST",
"tz_long":"Australia/Melbourne",
"lat":"-36.86999893",
"lon":"147.27000427",
"zip":"00000",
How do I populate the model to display in my view?
e.g.. #Model.city or #Html.Raw(Model.city)
I have no problem displaying the data via Javascript in my view and I can do this with XML and Html using the HtmlAgilityPack, I just can't work out how to do it with Json.
Add Newtonsoft.Json via NuGet, add the following using statements
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
and then use the following code to extract the data out of your JSON response.
JObject parsedJson = (JObject)JsonConvert.DeserializeObject(json);
JObject location = (JObject)parsedJson["location"];
WeatherWidget weatherWidget = new WeatherWidget();
weatherWidget.city = location["city"];
weatherWidget.lat = location["lat"];
weatherWidget.lon = location["lon"];

Deserialise dynamic json types

I want to deserialize json which returns different data for different parameters.
Mostly I get:
{"posts": [{ "id" : 1, "name":"post1" },{ "id" : 1, "name":"post1" }]}
But sometimes the data returned is
{"posts": false}
I want to deserialize this as the following class
public class GetReaderResponse
{
public IEnumerable<ReaderPost> posts {get; set;}
}
public class ReaderPost
{
public int id {get; set;}
public string name{get; set;}
}
I am using C#,json.net but not able to do this correctly.
Newtonsoft.Json.JsonConvert.DeserializeObject<GetReaderResponse>(dataString);
You could build a custom converter, but an easy way to handle this would be to write an error handler that detects errors with the posts property:
var settings = new JsonSerializerSettings();
settings.Error += (sender, args) =>
{
if (string.Equals("posts", args.ErrorContext.Path, StringComparison.OrdinalIgnoreCase))
{
var currentObject = args.CurrentObject as GetReaderResponse;
currentObject.posts = Enumerable.Empty<ReaderPost>();
args.ErrorContext.Handled = true;
}
};
GetReaderResponse resp =
JsonConvert.DeserializeObject<GetReaderResponse>(json, settings);
This sets posts to Enumerable.Empty<ReaderPost>. This is still a little unsatisfying because if any error occurs, the property will be set. You could build a full custom converter to do this as a more complete solution.
Here's a converter that will take care of this:
public class PostsConverter : JsonConverter
{
public override object ReadJson(
JsonReader reader,
Type objectType,
object existingValue,
JsonSerializer serializer)
{
JToken val = JValue.ReadFrom(reader);
object result = null;
if (val.Type == JTokenType.Array)
{
result = val.ToObject<IEnumerable<ReaderPost>>();
}
else if (val.Type == JTokenType.Boolean)
{
result = Enumerable.Empty<ReaderPost>();
}
return result;
}
public override void WriteJson(
JsonWriter writer,
object value,
JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override bool CanConvert (Type type)
{
return typeof(IEnumerable<ReaderPost>).IsAssignableFrom(type);
}
public override bool CanRead
{
get { return true; }
}
}
Usage:
var settings = new JsonSerializerSettings();
settings.Converters = new [] { new PostsConverter() };
GetReaderResponse resp =
JsonConvert.DeserializeObject<GetReaderResponse>(json, settings);
Example: https://dotnetfiddle.net/i9CXwp
By using JSON.NETs built in LINQ to JSON, you can try someting like this:
JObject jObject = JObject.Parse(json);
GetReaderResponse response = new GetReaderResponse();
if (jObject["posts"] is JArray)
response = jObject.ToObject<GetReaderResponse>();
// Do something with the response object.
where json variable is the json string you need to deserialize.
try this:
public class GetReaderResponse
{
public bool posts { get; set; }
public ReaderPost[] post { get; set; }
}
After reading #Ilija's comment I think I might have found a answer. I did not want not use string literals so I modified my class GetReaderResponse to look like below:
public class GetReaderResponse
{
public dynamic posts {get; set;}
public IEnumerable<ReaderPost> Posts
{
get
{
if (posts is bool )
return new ReaderPost[0];
return posts.ToObject<IEnumerable<ReaderPost>>();
}
}
}
Does this sound fine or does it look messy?

How to map complex object to simple fields

I have a JSON document similar to the following:
{
"aaa": [
{
"value": "ewfwefew"
}
],
"bbb": [
{
"value": "ewfewfe"
}
]
}
I need to deserialize this into something more clean such as:
public class MyEntity{
private String aaa;
private String bbb;
}
What's the best way to unwrap each array and extract the "value" field on deserialization?
#Tim Mac's response is correct, but you can make it more elegant by writing a custom deserializer for your MyEntity class.
It should be something like this:
private class MyEntityDeserializer implements JsonDeserializer<MyEntity> {
public MyEntity deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
JsonObject rootObj = json.getAsJsonObject();
String nid = rootObj
.get("nid")
.getAsJsonArray()
.get(0)
.getAsJsonObject()
.get("value")
.getAsString();
String uuid = rootObj
.get("uuid")
.getAsJsonArray()
.get(0)
.getAsJsonObject()
.get("value")
.getAsString();
MyEntity entity = new MyEntity(nid, uuid);
return entity;
}
}
Then you have to register the TypeAdapter with:
Gson gson = new GsonBuilder().registerTypeAdapter(MyEntity.class, new MyEntityDeserializer()).create();
And finally you just have to parse your JSON as usual, with:
MyEntity entity = gson.fromJson(yourJsonString, MyEntity.class);
Gson will automatically use your custom deserializer to parse your JSON into your MyEntity class.
If you can't change the json that you're getting, you might consider deserializing it the way it is, and then converting it to something more manageable?
public class TmpEntity {
public Value[] nid {get;set;}
public Value[] uuid {get;set;}
}
public class Value {
public string value {get;set;}
}
public class MyEntity {
public string nid {get;set;}
public string uuid {get;set;}
}
var tmp = ...; //deserialize using javascriptserializer
var converted = tmp.Select(a => new MyEntity()
{
nid = a.nid.First().value,
uuid = a.uuid.First().value
}

Not Getting the Root Name in JSON Format using WCF Rest

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.