Built in JSON parser in .NET framework [duplicate] - json

I'm trying to build a Metro application for Windows 8 on Visual Studio 2011.
and while I'm trying to do that, I'm having some issues on how to parse JSON without JSON.NET library (It doesn't support the metro applications yet).
Anyway, I want to parse this:
{
"name":"Prince Charming",
"artist":"Metallica",
"genre":"Rock and Metal",
"album":"Reload",
"album_image":"http:\/\/up203.siz.co.il\/up2\/u2zzzw4mjayz.png",
"link":"http:\/\/f2h.co.il\/7779182246886"
}

You can use the classes found in the System.Json Namespace which were added in .NET 4.5. You need to add a reference to the System.Runtime.Serialization assembly
The JsonValue.Parse() Method parses JSON text and returns a JsonValue:
JsonValue value = JsonValue.Parse(#"{ ""name"":""Prince Charming"", ...");
If you pass a string with a JSON object, you should be able to cast the value to a JsonObject:
using System.Json;
JsonObject result = value as JsonObject;
Console.WriteLine("Name .... {0}", (string)result["name"]);
Console.WriteLine("Artist .. {0}", (string)result["artist"]);
Console.WriteLine("Genre ... {0}", (string)result["genre"]);
Console.WriteLine("Album ... {0}", (string)result["album"]);
The classes are quite similar to those found in the System.Xml.Linq Namespace.

I use this...but have never done any metro app development, so I don't know of any restrictions on libraries available to you. (note, you'll need to mark your classes as with DataContract and DataMember attributes)
public static class JSONSerializer<TType> where TType : class
{
/// <summary>
/// Serializes an object to JSON
/// </summary>
public static string Serialize(TType instance)
{
var serializer = new DataContractJsonSerializer(typeof(TType));
using (var stream = new MemoryStream())
{
serializer.WriteObject(stream, instance);
return Encoding.Default.GetString(stream.ToArray());
}
}
/// <summary>
/// DeSerializes an object from JSON
/// </summary>
public static TType DeSerialize(string json)
{
using (var stream = new MemoryStream(Encoding.Default.GetBytes(json)))
{
var serializer = new DataContractJsonSerializer(typeof(TType));
return serializer.ReadObject(stream) as TType;
}
}
}
So, if you had a class like this...
[DataContract]
public class MusicInfo
{
[DataMember]
public string Name { get; set; }
[DataMember]
public string Artist { get; set; }
[DataMember]
public string Genre { get; set; }
[DataMember]
public string Album { get; set; }
[DataMember]
public string AlbumImage { get; set; }
[DataMember]
public string Link { get; set; }
}
Then you would use it like this...
var musicInfo = new MusicInfo
{
Name = "Prince Charming",
Artist = "Metallica",
Genre = "Rock and Metal",
Album = "Reload",
AlbumImage = "http://up203.siz.co.il/up2/u2zzzw4mjayz.png",
Link = "http://f2h.co.il/7779182246886"
};
// This will produce a JSON String
var serialized = JSONSerializer<MusicInfo>.Serialize(musicInfo);
// This will produce a copy of the instance you created earlier
var deserialized = JSONSerializer<MusicInfo>.DeSerialize(serialized);

For those who do not have 4.5, Here is my library function that reads json. It requires a project reference to System.Web.Extensions.
using System.Web.Script.Serialization;
public object DeserializeJson<T>(string Json)
{
JavaScriptSerializer JavaScriptSerializer = new JavaScriptSerializer();
return JavaScriptSerializer.Deserialize<T>(Json);
}
Usually, json is written out based on a contract. That contract can and usually will be codified in a class (T). Sometimes you can take a word from the json and search the object browser to find that type.
Example usage:
Given the json
{"logEntries":[],"value":"My Code","text":"My Text","enabled":true,"checkedIndices":[],"checkedItemsTextOverflows":false}
You could parse it into a RadComboBoxClientState object like this:
string ClientStateJson = Page.Request.Form("ReportGrid1_cboReportType_ClientState");
RadComboBoxClientState RadComboBoxClientState = DeserializeJson<RadComboBoxClientState>(ClientStateJson);
return RadComboBoxClientState.Value;

I needed a JSON serializer and deserializer without any 3rd party dependency or nuget, that can support old systems, so you don't have to choose between Newtonsoft.Json, System.Text.Json, DataContractSerializer, JavaScriptSerializer, etc. depending on the target platform.
So I have started this open source (MIT) project here:
https://github.com/smourier/ZeroDepJson
It's just one C# file ZeroDepJson.cs, compatible with .NET Framework 4.x to .NET Core, and .NET 5.
Note it's probably not as good as all the aforementioned libraries (especially in performance area), but it should be reasonably ok and friction-free.

Have you tried using JavaScriptSerializer ?
There's also DataContractJsonSerializer

I have written a small construct to do that long back, it requires System.Runtime.Serialization.Json namespace. It uses DataContractJsonSerializer to serialize & deserialize object with a static method JConvert.
It works with small set of data but haven't tested with big data source.
JsonHelper.cs
// Json Serializer without NewtonSoft
public static class JsonHelper
{
public static R JConvert<P,R>(this P t)
{
if(typeof(P) == typeof(string))
{
var return1 = (R)(JsonDeserializer<R>(t as string));
return return1;
}
else
{
var return2 = (JsonSerializer<P>(t));
R result = (R)Convert.ChangeType(return2, typeof(R));
return result;
}
}
private static String JsonSerializer<T>(T t)
{
var stream1 = new MemoryStream();
var ser = new DataContractJsonSerializer(typeof(T));
ser.WriteObject(stream1, t);
stream1.Position = 0;
var sr = new StreamReader(stream1);
return (sr.ReadToEnd());
}
private static T JsonDeserializer<T>(string jsonString)
{
T deserializedUser = default(T);
var ms = new MemoryStream(Encoding.UTF8.GetBytes(jsonString));
var ser = new DataContractJsonSerializer(typeof(T));
deserializedUser = (T)ser.ReadObject(ms);// as T;
ms.Close();
return deserializedUser;
}
}
Syntax:
To use the JsonHelper you need to call
JConvert<string,object>(str); //to Parse string to non anonymous <object>
JConvert<object,string>(obj); //to convert <obj> to string
Example:
Suppose we have a class person
public class person
{
public string FirstName {get;set;}
public string LastName {get;set;}
}
var obj = new person();//"vinod","srivastav");
obj.FirstName = "vinod";
obj.LastName = "srivastav";
To convert the person object we can call:
var asText = JsonHelper.JConvert<person,string>(obj); //to convert <obj> to string
var asObject = JsonHelper.JConvert<string,person>(asText); //to convert string to non-anonymous object

You can use DataContractJsonSerializer. See this link for more details.

using System;
using System.IO;
using System.Runtime.Serialization.Json;
using System.Text;
namespace OTL
{
/// <summary>
/// Before usage: Define your class, sample:
/// [DataContract]
///public class MusicInfo
///{
/// [DataMember(Name="music_name")]
/// public string Name { get; set; }
/// [DataMember]
/// public string Artist{get; set;}
///}
/// </summary>
/// <typeparam name="T"></typeparam>
public class OTLJSON<T> where T : class
{
/// <summary>
/// Serializes an object to JSON
/// Usage: string serialized = OTLJSON<MusicInfo>.Serialize(musicInfo);
/// </summary>
/// <param name="instance"></param>
/// <returns></returns>
public static string Serialize(T instance)
{
var serializer = new DataContractJsonSerializer(typeof(T));
using (var stream = new MemoryStream())
{
serializer.WriteObject(stream, instance);
return Encoding.Default.GetString(stream.ToArray());
}
}
/// <summary>
/// DeSerializes an object from JSON
/// Usage: MusicInfo deserialized = OTLJSON<MusicInfo>.Deserialize(json);
/// </summary>
/// <param name="json"></param>
/// <returns></returns>
public static T Deserialize(string json)
{
if (string.IsNullOrEmpty(json))
throw new Exception("Json can't empty");
else
try
{
using (var stream = new MemoryStream(Encoding.Default.GetBytes(json)))
{
var serializer = new DataContractJsonSerializer(typeof(T));
return serializer.ReadObject(stream) as T;
}
}
catch (Exception e)
{
throw new Exception("Json can't convert to Object because it isn't correct format.");
}
}
}
}

Related

Dictionary<string,long> is not being serialized

I am trying to serialize a simple class:
public class Offer_RPC
{
/// <summary>
/// this dictionary contains your requested additions ans substractions, in mojos.<br/>
/// if you wan to offer an nft for example, use the launcher id such as <br/>
/// "1": 1000000000000 (offer for 1 xch) <br/>
/// "cc4138f8debe4fbedf26ccae0f965be19c67a49d525f1416c0749c3c865dxxx", -1 <br/>
/// </summary>
public Dictionary<string, long> offer = new Dictionary<string, long>();
public override string ToString()
{
JsonSerializerOptions options = new JsonSerializerOptions();
options.WriteIndented = false;
options.DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull;
string jsonString = JsonSerializer.Serialize(this, options: options);
return jsonString;
}
}
when calling .ToString(), the resulting json is {}
This is my test method:
[Fact]
public void TestOffer()
{
Offer_RPC test = new Offer_RPC();
test.offer.Add("1", 1);
test.offer.Add("2", -1);
string json = test.ToString();
}
offer is a field and by default fields are not serialized by the System.Text.Json serialiser.
You can:
Make offer a property:public Dictionary<string, long> Offer { get; } = new ...
Include fields:
var options = new JsonSerializerOptions
{
IncludeFields = true,
};
var json = JsonSerializer.Serialize(o, options);
just fix the class offer property by adding a getter
public Dictionary<string, long> offer { get; } = new Dictionary<string, long>();
The Issue is that offer is not a public Property. The class should look like this:
public class Offer_RPC
{
public Offer_RPC()
{
offer = new Dictionary<string, long>();
}
/// <summary>
/// this dictionary contains your requested additions ans substractions, in mojos.<br/>
/// if you wan to offer an nft for example, use the launcher id such as <br/>
/// "1": 1000000000000 (offer for 1 xch) <br/>
/// "cc4138f8debe4fbedf26ccae0f965be19c67a49d525f1416c0749c3c865dxxx", -1 <br/>
/// </summary>
public Dictionary<string, long> offer { get; set; }
public override string ToString()
{
JsonSerializerOptions options = new JsonSerializerOptions();
options.WriteIndented = false;
options.DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull;
string jsonString = JsonSerializer.Serialize(this, options: options);
return jsonString;
}
}

System.Text.Json.JsonSerializer.Deserialize returning object with all fields null in .Net Core 3.1 [duplicate]

I am converting my newtonsoft implementation to new JSON library in .net core 3.0. I have the following code
public static bool IsValidJson(string json)
{
try
{
JObject.Parse(json);
return true;
}
catch (Exception ex)
{
Logger.ErrorFormat("Invalid Json Received {0}", json);
Logger.Fatal(ex.Message);
return false;
}
}
I am not able to find any equivalent for JObject.Parse(json);
Also what will be the attribute JsonProperty equivalent
public class ResponseJson
{
[JsonProperty(PropertyName = "status")]
public bool Status { get; set; }
[JsonProperty(PropertyName = "message")]
public string Message { get; set; }
[JsonProperty(PropertyName = "Log_id")]
public string LogId { get; set; }
[JsonProperty(PropertyName = "Log_status")]
public string LogStatus { get; set; }
public string FailureReason { get; set; }
}
One more thing i will be looking for the equivalent of Formating.None.
You are asking a few questions here:
I am not able to find any equivalent for JObject.Parse(json);
You can use JsonDocument to parse and examine any JSON, starting with its RootElement. The root element is of type JsonElement which represents any JSON value (primitive or not) and corresponds to Newtonsoft's JToken.
But do take note of this documentation remark:
This class utilizes resources from pooled memory to minimize the impact of the garbage collector (GC) in high-usage scenarios. Failure to properly dispose this object will result in the memory not being returned to the pool, which will increase GC impact across various parts of the framework.
When you need to use a JsonElement outside the lifetime of its document, you must clone it:
Gets a JsonElement that can be safely stored beyond the lifetime of the original JsonDocument.
Also note that JsonDocument is currently read-only and does not provide an API for creating or modifying JSON. There is an open issue Issue #39922: Writable Json DOM tracking this.
An example of use is as follows:
//https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8#using-declarations
using var doc = JsonDocument.Parse(json);
//Print the property names.
var names = doc.RootElement.EnumerateObject().Select(p => p.Name);
Console.WriteLine("Property names: {0}", string.Join(",", names)); // Property names: status,message,Log_id,Log_status,FailureReason
//Re-serialize with indentation.
using var ms = new MemoryStream();
using (var writer = new Utf8JsonWriter(ms, new JsonWriterOptions { Indented = true }))
{
doc.WriteTo(writer);
}
var json2 = Encoding.UTF8.GetString(ms.GetBuffer(), 0, checked((int)ms.Length));
Console.WriteLine(json2);
Also what will be the attribute JsonProperty equivalent?
Attributes that can control JsonSerializer are placed in the System.Text.Json.Serialization namespace and inherit from an abstract base class JsonAttribute. Unlike JsonProperty, there is no omnibus attribute that can control all aspects of property serialization. Instead there are specific attributes to control specific aspects.
As of .NET Core 3 these include:
[JsonPropertyNameAttribute(string)]:
Specifies the property name that is present in the JSON when serializing and deserializing. This overrides any naming policy specified by JsonNamingPolicy.
This is attribute you want to use to control the serialized names of your ResponseJson class:
public class ResponseJson
{
[JsonPropertyName("status")]
public bool Status { get; set; }
[JsonPropertyName("message")]
public string Message { get; set; }
[JsonPropertyName("Log_id")]
public string LogId { get; set; }
[JsonPropertyName("Log_status")]
public string LogStatus { get; set; }
public string FailureReason { get; set; }
}
[JsonConverterAttribute(Type)]:
When placed on a type, the specified converter will be used unless a compatible converter is added to the JsonSerializerOptions.Converters collection or there is another JsonConverterAttribute on a property of the same type.
Note that the documented priority of converters -- Attribute on property, then the Converters collection in options, then the Attribute on type -- differs from the documented order for Newtonsoft converters, which is the JsonConverter defined by attribute on a member, then the JsonConverter defined by an attribute on a class, and finally any converters passed to the JsonSerializer.
[JsonExtensionDataAttribute] - corresponds to Newtonsoft's [JsonExtensionData].
[JsonIgnoreAttribute] - corresponds to Newtonsoft's [JsonIgnore].
When writing JSON via Utf8JsonWriter, indentation can be controlled by setting JsonWriterOptions.Indented to true or false.
When serializing to JSON via JsonSerializer.Serialize, indentation can be controlled by setting JsonSerializerOptions.WriteIndented to true or false.
Demo fiddle here showing serialization with JsonSerializer and parsing with JsonDocument.
This link should get you going, snippets of which I copied below.
https://devblogs.microsoft.com/dotnet/try-the-new-system-text-json-apis/
WeatherForecast Deserialize(string json)
{
var options = new JsonSerializerOptions
{
AllowTrailingCommas = true
};
return JsonSerializer.Parse<WeatherForecast>(json, options);
}
class WeatherForecast {
public DateTimeOffset Date { get; set; }
// Always in Celsius.
[JsonPropertyName("temp")]
public int TemperatureC { get; set; }
public string Summary { get; set; }
// Don't serialize this property.
[JsonIgnore]
public bool IsHot => TemperatureC >= 30;
}

How to convert json dynamic object to c# entity

When I make mvc ajax json post applicaiton, there is a trouble to convert json dynamic object to entity.
In my app, movie is a business entity, json object has row status property than movie entity. When json data is posted to mvc server side, it can be converted to dynamic object, everyting is ok in this stage. But after handling some logic to each row status, it is needed to convert dynamic object to movie business entity, then begin database transaction logic. But there is a troulbe even I try different method to cast the object.
please did someone use the same cast method? thanks your advice or reply.
public class movie
{
public int id
{
get;
set;
}
public string title
{
get;
set;
}
}
/// <summary>
/// Convert Json Object to Entity
/// </summary>
/// <param name="id">ajax post value
/// format: {"id": "{\"id\": 1, \"title\": \"sharlock\", \"RowStatus\": \"deleted\"}"}
/// </param>
[AllowAnonymous]
[HttpPost]
public void DoJsonSimple(string id)
{
string title;
var entity = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(id);
//*** entity is dynamic object
//*** entity.id, entity.title and entity.RowStauts can be accessed.
int first = entity.id;
var status = entity.RowStatus;
if (status == "deleted")
{
//*** m1 is null
//*** m1.title can not be accessed
movie m1 = entity as movie;
title = m1.title;
//*** m2 is an empty object
//*** m2.id is 0, m2.title is null
var m2 = AutoMapperHelper<dynamic, movie>.AutoConvertDynamic(entity);
title = m2.title;
//*** Exception: Object must implement IConvertible.
var m3 = EmitMapper.EMConvert.ChangeTypeGeneric<dynamic, movie>(entity);
title = m3.title;
}
}
Just create another class for the rows.
public class Request
{
[JsonProperty("id")]
public string Json { get; set; }
}
public class Movie
{
[JsonProperty("id")]
public int Id { get; set; }
[JsonProperty("title")]
public string Title { get; set; }
}
// either this for variant 1...
public class Row
{
public string RowStatus { get; set; }
}
// or that for variant 2...
public class MovieRow : Movie
{
public string RowStatus { get; set; }
}
[AllowAnonymous]
[HttpPost]
public void DoJsonSimple_Variant1(string id)
{
var json = JsonConvert.DeserializeObject<Request>(id).Json;
var entity = JsonConvert.DeserializeObject<MovieRow>(json);
var row = JsonConvert.DeserializeObject<Row>(json);
switch (row.RowStatus)
{
case "deleted":
// delete entity
break;
// ...
}
// ...
}
[AllowAnonymous]
[HttpPost]
public void DoJsonSimple_Variant2(string id)
{
var json = JsonConvert.DeserializeObject<Request>(id).Json;
var row = JsonConvert.DeserializeObject<MovieRow>(json);
var entity = (Movie)row;
switch (row.RowStatus)
{
case "deleted":
// delete entity
break;
// ...
}
// ...
}

Deserializing a class with a Queue<T> with Newtonsoft.Json

I have a class that has a property of type Queue. When trying to deserialize the JSON, I get the following error:
Type specified in JSON 'ConsoleApplication1.Task[], ConsoleApplication1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' is not compatible with 'System.Collections.Generic.Queue`1[[ConsoleApplication1.Task, ConsoleApplication1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'. Path 'Tasks.$type', line 1, position 140.
I have included the sample application below and I am using Newtonsoft.Json 4.5.10.15407.
The reason I am using a Queue instead of List or Dictionary is because I must preserve insert order. I've also tried searching in the docs and other questions but haven't really found anything concrete. Any help is much appreciated. Thank you.
namespace ConsoleApplication1
{
using System;
using System.Collections.Generic;
using System.Text;
using Newtonsoft.Json;
class Program
{
static void Main(string[] args)
{
Message message = new Message
{
MessageID = 1,
Tasks = new Queue<Task>()
};
message.Tasks.Enqueue(new Task{TaskId = 1, Message = "Test1", Parameters = "Param1"});
message.Tasks.Enqueue(new Task{TaskId = 2, Message = "Test2", Parameters = "Param2"});
byte[] bSerialized = SerializeJsonWithPrefix(message);
Message deserializedMessage = DeserializeJson(bSerialized, typeof (Message));
}
public static byte[] SerializeJsonWithPrefix(Message item)
{
JsonSerializerSettings jss = new JsonSerializerSettings();
jss.TypeNameHandling = TypeNameHandling.All;
return Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(item, jss));
}
public static Message DeserializeJson(byte[] ueaData, Type concreteType)
{
JsonSerializerSettings jss = new JsonSerializerSettings();
jss.TypeNameHandling = TypeNameHandling.All;
// --- Error occurs here ---
var result = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(ueaData), concreteType, jss);
return (Message)result;
}
}
public class Message
{
public int MessageID { get; set; }
public Queue<Task> Tasks { get; set; }
}
public class Task
{
public int TaskId { get; set; }
public string Message { get; set; }
public string Parameters { get; set; }
}
}
Version 5 solves your problem.
I stick to List<T> and Dictionary<string, T> when using JSON.NET serialization, where T is some JSON-serializable type. These correspond nicely to the JSON array and object types (see json.org).
If you serialize a List<T> and then deserialize it, JSON.NET will of course maintain the ordering. I would advise just translating between your Queue<T> and a List<T> for serialization, rather than trying to add behavior for directly serializing the Queue<T>.

Deserializing $ref and $id

So I'm trying to deserialize an object that has properties: $ref and $id. I have tried going between Dictionary as well as an object where I have specified namingconventions via JsonPropertyAttribute. Serialization works, but deserialization doesn't. The error I keep getting is:
Additional text found in JSON string
after finishing deserializing object.
Sample code where all three samples, fail.
[Serializable]
public class Ref
{
[JsonProperty(PropertyName = "$ref")]
public virtual string RefName { get; set; }
[JsonProperty(PropertyName = "$id")]
public virtual int Id { get; set; }
}
[Serializable]
public class Child
{
public virtual string Name { get; set; }
[JsonProperty(IsReference = true)]
public virtual Ref Father { get; set; }
}
class Program
{
static void Main(string[] args)
{
//Additional text found in JSON string after finishing deserializing object.
//Test 1
var reference = new Dictionary<string, object>();
reference.Add("$ref", "Persons");
reference.Add("$id", 1);
var child = new Dictionary<string, object>();
child.Add("_id", 2);
child.Add("Name", "Isabell");
child.Add("Father", reference);
var json = JsonConvert.SerializeObject(child);
var obj = JsonConvert.DeserializeObject<Dictionary<string, object>>(json); //Exception
//Test 2
var refOrg = new Ref {RefName = "Parents", Id = 1};
var refSer = JsonConvert.SerializeObject(refOrg);
var refDeser = JsonConvert.DeserializeObject<Ref>(refSer); //Exception
//Test 3
var childOrg = new Child {Father = refOrg, Name = "Isabell"};
var childSer = JsonConvert.SerializeObject(childOrg);
var childDeser = JsonConvert.DeserializeObject<Child>(refSer); //Exception
}
}
I have the same issue when trying to deserialize a swagger/json schema document. The solution is:
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.MetadataPropertyHandling = MetadataPropertyHandling.Ignore;
You'll find that $ref & $id are special properties used by Json.NET to manage multiple instances of objects in a single object graph.
By putting these keys into your dictionary the deserialize process is trying to parse these as references to objects that don't exist.
Try altering the keys.
This answer worked for me: Json.Net adding $id to EF objects despite setting PreserveReferencesHandling to "None"
In your implementation of DefaultContractResolver/IContractResolver, add this;
public override JsonContract ResolveContract(Type type) {
var contract = base.ResolveContract(type);
contract.IsReference = false;
return contract;
}