Jobject.Parse VS JSONconvert.Deserializeobject

JObject.Parse vs JsonConvert.DeserializeObject

The LINQ-to-JSON API (JObject, JToken, etc.) exists to allow working with JSON without needing to know its structure ahead of time. You can deserialize any arbitrary JSON using JToken.Parse, then examine and manipulate its contents using other JToken methods. LINQ-to-JSON also works well if you just need one or two values from the JSON (such as the name of a county).

JsonConvert.DeserializeObject, on the other hand, is mainly intended to be used when you DO know the structure of the JSON ahead of time and you want to deserialize into strongly typed classes. For example, here's how you would get the full set of county data from your JSON into a list of County objects.

class Program
{
static void Main(string[] args)
{
string countiesJson = "{'Everything':[{'county_name':null,'description':null,'feat_class':'Civil','feature_id':'36865',"
+"'fips_class':'H1','fips_county_cd':'1','full_county_name':null,'link_title':null,'url':'http://www.alachuacounty.us/','name':'Alachua County'"+ ",'primary_latitude':'29.7','primary_longitude':'-82.33','state_abbreviation':'FL','state_name':'Florida'},"+
"{'county_name':null,'description':null,"+ "'feat_class':'Civil','feature_id':'36866','fips_class':'H1','fips_county_cd':'3','full_county_name':null,'link_title':null,'url':'http://www.bakercountyfl.org/','name':'Baker County','primary_latitude':'30.33','primary_longitude':'-82.29','state_abbreviation':'FL','state_name':'Florida'}]}";

foreach (County c in JsonParseCounties(countiesJson))
{
Console.WriteLine(string.Format("{0}, {1} ({2},{3})", c.name,
c.state_abbreviation, c.primary_latitude, c.primary_longitude));
}
}

public static List<County> JsonParseCounties(string jsonText)
{
return JsonConvert.DeserializeObject<RootObject>(jsonText).Counties;
}
}

public class RootObject
{
[JsonProperty("Everything")]
public List<County> Counties { get; set; }
}

public class County
{
public string county_name { get; set; }
public string description { get; set; }
public string feat_class { get; set; }
public string feature_id { get; set; }
public string fips_class { get; set; }
public string fips_county_cd { get; set; }
public string full_county_name { get; set; }
public string link_title { get; set; }
public string url { get; set; }
public string name { get; set; }
public string primary_latitude { get; set; }
public string primary_longitude { get; set; }
public string state_abbreviation { get; set; }
public string state_name { get; set; }
}

Notice that Json.Net uses the type argument given to the JsonConvert.DeserializeObject method to determine what type of object to create.

Of course, if you don't specify a type when you call DeserializeObject, or you use object or dynamic, then Json.Net has no choice but to deserialize into a JObject. (You can see for yourself that your dynamic variable actually holds a JObject by checking jResults.GetType().FullName.) So in that case, there's not much difference between JsonConvert.DeserializeObject and JToken.Parse; either will give you the same result.

JSon.Net JObject.FromObject Vs JsonConvert.DeserializeObjectJObject(JsonConvert.SerializeObject(obj));

This is faster:

JObject.FromObject(obj);

It builds a JObject directly from the object. The other method serializes the object to JSON a JSON string and then parses the JSON to build a JObject.

Documentation: JObject.FromObject

JObject Not Parsing Values I need

  1. Take json["links"] as JArray.
  2. Use Linq to retrieve url from the element in (1) and cast it to string.
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json.Linq;

JObject json = JObject.Parse(contents);
JArray array = json["links"] as JArray;

List<string> links = array.Select(x => (string)x["url"]).ToList();

Sample demo on .NET Fiddle

How to deserialize a JObject to .NET object

According to this post, it's much better now:

// pick out one album
JObject jalbum = albums[0] as JObject;

// Copy to a static Album instance
Album album = jalbum.ToObject<Album>();

Documentation: Convert JSON to a Type

Newtonsoft JSON Deserialize Dynamically

Have you looked into using JsonLinq and JObject.Parse()? You can then using something like the following:

string Data = "{\"t\":\"1339886\",\"a\":true,\"data\":[],\"Type\":[['Ants','Biz','Tro']]}";
JObject J = JObject.Parse(Data);
string[] Types = J["Type"][0].ToObject<string[]>();

Note: I didn't test this against your data structure.

Deserialize a class to a dictionary in c# using JsonConvert.DeserializeObject or JObject.Parse

Finally I could resolve the issue:

For the first problem as suggested by @Camilo I created a wrapper.

For the second I created a custom JsonConverter which made the job for me like below.

internal class TranslationsToDictionaryObjectConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(List<CountryInfoModel>).IsAssignableFrom(objectType)
|| typeof(List<CurrencyInfoModel>).IsAssignableFrom(objectType);
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JToken token = JToken.Load(reader);
Dictionary<string, string> dict = new Dictionary<string, string>();
try
{
foreach (var item in token)
{
dict.Add(item["languageCode"].ToString(), item["translatedName"].ToString());
}
}
catch
{
// ignored
}

return dict;
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
}
}

After that the model would look like:

[Serializable]
public class CountryInfoModel
{
public int BwinId { get; set; }

public string TranslatedName { get; set; }

public string TwoLetterCode { get; set; }

public bool LoginAllowed { get; set; }

public bool RegistrationAllowed { get; set; }

[JsonConverter(typeof(TranslationsToDictionaryObjectConverter))]
public Dictionary<string, string> Translations { get; set; }
}

Why isn't JObject converting the JSON string?

You are getting an error because "\"User sent null or empty data\"" is not a JSON object, so it cannot be parsed by JObject.Parse. Instead you should use JToken.Parse. This method can handle any kind of JSON -- objects, arrays and simple values. The IsValid extension method is defined to work on JToken, so it should still work fine with this change.

As an aside, when the JToken validates successfully, you don't need to deserialize the JSON a second time with JsonConvert.DeserializeObject<T>(). You can convert the token to your object directly using JToken.ToObject<T>() instead.

So in other words, change this code:

var jObject = JObject.Parse(json);
return jObject.IsValid(parsedSchema) ? JsonConvert.DeserializeObject<T>(json) : default(T);

To this:

var jToken = JToken.Parse(json);
return jToken.IsValid(parsedSchema) ? jToken.ToObject<T>() : default(T);

To be extra safe you could put a try/catch block around the parsing. That way if you get a string that isn't even JSON at all, you can handle that as well. So then you would have:

internal static T TryParseJson<T>(this string json, string schema) where T : new()
{
var parsedSchema = JSchema.Parse(schema);
try
{
var jToken = JToken.Parse(json);
return jToken.IsValid(parsedSchema) ? jToken.ToObject<T>() : default(T);
}
catch (JsonException ex)
{
// optionally log the exception here
return default(T);
}
}

Deserializing and working with a JSON object

First you need to create a class to work with the returned objects (assuming you know what you are getting ahead of time).

public class ShoppingbasketItem
{
public double price { get; set; }
public string product { get; set; }
public int quantity { get; set; }
public int total { get; set; }
}
public class Shoppingbasket
{
public List<ShoppingbasketItem> shoppingbasket { get; set; }
}

Then you can deserialize the objects into your C# code and then do whatever you would need to with them from there.

var products = Newtonsoft.Json.JsonConvert.DeserializeObject<Shoppingbasket>(Request.Cookies.Get("wrkb").Value);

So to compute a sum of the total you could just iterate the list from the basket.

double totalSum = 0.0;
foreach(var item in products.shoppingbasket)
{
totalSum += item.quantity * item.price;
}

Edit
To achieve the grouping you are looking for, you could do something like this. It is probably not the best solution, but off the top of my head it is what I thought of.

var grouped = new Dictionary<string, ShoppingbasketItem>();

foreach (var item in products.shoppingbasket)
{
ShoppingbasketItem temp = null;
if (grouped.TryGetValue(item.product, out temp))
{
temp.quantity += item.quantity;
temp.total += item.total;
}
else
{
grouped[item.product] = item;
}
}

JSON JObject.Parse modifies json string

It does not really modify your string, it just parses your date string into DateTime object when you call JObject.Parse. If you do this:

var obj = JObject.Parse(json);
var values = (JArray) obj["valuesList"];
var time = (JValue) values[0]["TimeCaptured"];
Console.WriteLine(time.Value.GetType());

You notice that time.Value is of type DateTime. Then you do this:

JsonConvert.DeserializeObject<List<IValuePacket>>(jobject["valuesList"].ToString());

By doing that you convert valueList back to json, but now TimeCaptured is DateTime and not a string, so that DateTime object is converted to json string using whatever date time format is used by JSON.NET by default.

You can avoid parsing strings that look like dates to .NET DateTime objects by parsing json to JObject like this:

JObject obj;
using (var reader = new JsonTextReader(new StringReader(json))) {
// DateParseHandling.None is what you need
reader.DateParseHandling = DateParseHandling.None;
obj = JObject.Load(reader);
}

Then type of TimeCaptured will be string, as you expect.

Side note: there is no need to convert JToken back to string and then call JsonConvert.Deserialize on that string. Instead, do this:

var values = obj["valuesList"].ToObject<List<IValuePacket>>();


Related Topics



Leave a reply



Submit