Using System.Json for non-Silverlight projects? - c#

Any idea on how to do it? If not possible, what's a good JSON library for C#?

System.Json is now available in non-Silverlight projects via NuGet (.Net's package management system) and is hopefully going to be released as part of the core framework in vnext. The NuGet package is named JsonValue.
Imagine that we have the following JSON in the string variable json:
[{"a":"foo","b":"bar"},{"a":"another foo","b":"another bar"}]
We can get write the value "another bar" to the console using the following code:
using System.Json;
dynamic jsonObj = JsonValue.Parse(json);
var node = jsonObj[1].b;
System.Console.WriteLine(node.Value);

Here's an extenstion method to serialize any object instance to JSON:
public static class GenericExtensions
{
public static string ToJsonString<T>(this T input)
{
string json;
DataContractJsonSerializer ser = new DataContractJsonSerializer(input.GetType());
using (MemoryStream ms = new MemoryStream())
{
ser.WriteObject(ms, input);
json = Encoding.Default.GetString(ms.ToArray());
}
return json;
}
}
You'll need to add a reference to System.ServiceModel.Web to use the DataContractSerializer.

Scott Guthrie blogged about this
http://weblogs.asp.net/scottgu/archive/2007/10/01/tip-trick-building-a-tojson-extension-method-using-net-3-5.aspx

If you're just looking for JSON encoding/decoding, there is an official System.Web extension library from Microsoft that does it, odds are you probably already have this assembly (System.Web.Extensions):
http://msdn.microsoft.com/en-us/library/system.web.script.serialization.javascriptserializer.aspx
Example:
using System;
using System.Web.Script.Serialization;
class App
{
static void Main(string[] args = null)
{
JavaScriptSerializer jss = new JavaScriptSerializer();
String sJson = "{\"Name\": \"Your name\"}";
DesJson json = jss.Deserialize<DesJson>(sJson);
Console.WriteLine(json.Name);
}
}
class DesJson {
public string Name {get; set;}
}

Another option is to use Mono's implementation of System.Json,
I was able to backport it to C# 2.0 with a few minor changes.
You can simply download my C# 2.0 project from here.

Related

How to convert some RAW data from an API and save it into variables so i can work with them in C#

I'm working on a personal project. Its a C# app that communicates with some web services using an API.
i finally got the first raw data with this few lines:
var client = new RestClient("https://api.abcd.com/token");
var request = new RestRequest(Method.POST);
request.AddParameter("username", usr);
request.AddParameter("password", pass);
request.AddParameter("grant_type", "password");
and in postman the response (JSON) looks like :
{"access_token":"aaaaaaa","token_type":"bearer","expires_in":899,"refresh_token":"bbbbbbb",".issued":"Fri,
01 May 2020 16:11:36 GMT",".expires":"Fri, 01 May 2020 16:26:36
GMT",".refreshexpires":"Fri, 01 May 2020 17:11:36 GMT"}
my next step is to find the way to separate those key/value pair into different variables in C# so i can work with them.
thank you so much for the help.
But I guess for small purpose no need to create a class rather use weakly typed data structure like this:
dynamic responseObject = JsonConvert.DeserializeObject(responseString);
//then use every property like this
responseObject.accessToken ...
responseObject.token_type.....
But you need to use Newtonsoft.Json for this too.
You want to use a JSON deserialiser to do this.
So you would create a class:
public class Response {
public string accessToken {get; set;)
public string token_type {get; set;)
.....
}
And then use something like Newtonsoft.Json (available from NuGet) to deserialise:
using Newtonsoft.Json;
.....
var response = JsonConvert.Deserialise<Response>([RAW TEXT FROM REST CLIENT]);
You can look into using Json.Net which will allow you to deserialize the JSON into an object like so. Note you'll need to download the package and then add using Newtonsoft.Json;
{
"varone":"valueone"
}
public class MyJsonClass
{
//JsonProperty isn't strictly required but I personally think it helps when trying to deserialize for sanity sake
[JsonProperty("varone")]
public string VarOneValue { get; set; } //The value will be "valueone" on deserialization
}
var myobj = JsonConvert.DeserializeObject<MyJsonObject>(JSONDATA);
Console.Write(myobj.VarOneValue); //Will be "valueone"
Nuget CLI: Install-Package Newtonsoft.Json
Page: https://www.newtonsoft.com/json

PHP like serialized string in .NET

I have a legacy PHP application which is using PHP's serialize() method to serialize the class and store it to a file and there are other applications using this string using unserialize() method to create object of the serialized class and use the data associated. I need to achieve similar serialization technique in .NET so that the output is same as PHP. I am thinking to use Reflection for this but still need to identify how I will make use of that. I have also tried the .NET serialization but the output is totally different.
Is there any other way I can do this?
consider example below -
sample php class
class SerializeTest
{
var $test = 0;
var $test1 = "testing";
var $test2 = 1;
var $test3 = "testing1";
public function __construct()
{
echo serialize($this);
}
}
serialized string
O:13:"SerializeTest":4:{s:4:"test";i:0;s:5:"test1";s:7:"testing";s:5:"test2";i:1;s:5:"test3";s:8:"testing1";}
sample .NET Class
class SerializeDemo
{
internal int test = 0;
internal string test1 = "testing";
internal int test2 = 1;
internal string test3 = "testing3";
}
required serialized string
O:13:"SerializeTest":4:{s:4:"test";i:0;s:5:"test1";s:7:"testing";s:5:"test2";i:1;s:5:"test3";s:8:"testing1";}
Try the Sharp Serialization Library
Sharp Serialization Library serializes and deserializes primitives,
ArrayLists and Hashtables, compatible with PHP serialize(). Use it for
SOAP/Web Services communications where Hashtables cannot be passed
otherwise, or saving to a file readable by php.

.Net Standard 4.7.1 Could not load System.Private.CoreLib during serialization

I'm working on migrating most of my project to .Net Standard 2.0.
Last part of the project in .net standard 4.7.1 is a WCF front end.
This executable communicate with a .net core application throught a library Akka.net by ClientServiceReceptionist.
Network communication between application by akka.net work.
Except when an it try to serialize a ReadOnlyCollection.
In this case the system try to load a "System.Private.CoreLib.dll" that is not available.
I readed many issues with .net 4.6 using .net standard 2.0 libraries that must have been corrected in 4.7.1. I pass from package.config to PackageReference.
I tryed to used NewtonSoft as a serializer in place of Hyperion without progress.
Does anyone have an idea, a solution ?
Edit : 07-05-2018
The issue is throw in the WCF Entry Points when i sent a ClusterClient.Send object throught the ClusterClientReceptionist.
The object sent contains only boolean, string, Guid and array of string properties.
Edit 08-05-2018
The object sent look like this :
{
(string) "Path": "/user/ProcessOrderWorkflow",
"Message": {
"Order": {
"Data": {
(string)"Sentence": "i love my name",
"Options": {
(boolean)"Simplify" : true,
(IReadOnlyCollection<string>) LanguageAffinity : [ "FR", "EN" ]
}
},
"OrderQuery": {
"Verb": {
(string)"Verb": "Extract"
},
"Arguments": [
{
(string)"Argument": "Sentence"
},
{
(string)"Argument": "Meaning"
}
]
},
(Guid)"ProcessId": "0bfef4a5-c8a4-4816-81d1-6f7bf1477f65"
},
(string)"ReturnTypeFullName": "Viki.Api.Server.Data.SentenceMeaningMsg,, Viki.Api.Server.Data, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
},
(boolean)"LocalAffinity": false
}
Each of the object used in the hierachi is builded using the constructor.
All the properties are in readonly.
I tryed to serialize and deserialize the result on the WCF part before it's sent and it works.
var serializer = this._system.Serialization.FindSerializerFor(result);
var bytes = serializer.ToBinary(result);
var data = serializer.FromBinary(bytes, result.GetType());
The strange think is that it try to deserialize the object in the WCF part where it is sent and not in the LightHouse where the element should be received and transfert to a agent for processing.
This is a top result for request "Could not load System.Private.CoreLib" so I post the workaround for ASP.NET Core APIs and .NET clients.
If json serializer type handling set to auto
settings.TypeNameHandling = TypeNameHandling.Auto;
serializer will include type information for polymorphic types. After migration to .NET Core some clients reported exception and the response body contained following type descriptor:
"$type":"System.String[], System.Private.CoreLib"
In the API model property type was defined as IEnumerable<string> which forced serializer to include actual type for an Array. The solution was to replace IEnumerable<string> with string[] or any other concrete type which allowed serializer to omit the type descriptor.
If the above does not work, for instance when you use Dictionary<string, object> you can implement custom SerializationBinder:
public class NetCoreSerializationBinder : DefaultSerializationBinder
{
private static readonly Regex regex = new Regex(
#"System\.Private\.CoreLib(, Version=[\d\.]+)?(, Culture=[\w-]+)(, PublicKeyToken=[\w\d]+)?");
private static readonly ConcurrentDictionary<Type, (string assembly, string type)> cache =
new ConcurrentDictionary<Type, (string, string)>();
public override void BindToName(Type serializedType, out string assemblyName, out string typeName)
{
base.BindToName(serializedType, out assemblyName, out typeName);
if (cache.TryGetValue(serializedType, out var name))
{
assemblyName = name.assembly;
typeName = name.type;
}
else
{
if (assemblyName.AsSpan().Contains("System.Private.CoreLib".AsSpan(), StringComparison.OrdinalIgnoreCase))
assemblyName = regex.Replace(assemblyName, "mscorlib");
if (typeName.AsSpan().Contains("System.Private.CoreLib".AsSpan(), StringComparison.OrdinalIgnoreCase))
typeName = regex.Replace(typeName, "mscorlib");
cache.TryAdd(serializedType, (assemblyName, typeName));
}
}
}
And register it in JsonSerializerSettings:
settings.SerializationBinder = new NetCoreSerializationBinder();
Note: .AsSpan() for string comparison was added for backwards compatibility with .NET Framework. It doesn't harm, but not required for .NET Core 3.1+, feel free to drop it.
So this is what I thought the issue might be... The problem is that transmitting serialized content between a .NET Core application and a .NET Framework application using a polymorphic serializer like JSON.NET or Hyperion is an unsupported operation in Akka.NET at least, but also in any other runtime where the users uses CLR types as the wire format of the messages.
A brief explanation as to why we don't support this in Akka.NET, from the v1.3.0 release notes:
As a side note: Akka.NET on .NET 4.5 is not wire compatible with Akka.NET on .NET Core; this is due to fundamental changes made to the base types in the CLR on .NET Core. It's a common problem facing many different serializers and networking libraries in .NET at the moment. You can use a X-plat serializer we've developed here: #2947 - please comment on that thread if you're considering building hybrid .NET and .NET Core clusters.
The "fundamental changes" in this case being that the namespaces for types like string are different on .NET 4.* and .NET Core, thus a polymorphic serializer that doesn't account for those differences will throw this type of exception.
We do have a workaround available here if you'd like to use it:
https://github.com/akkadotnet/akka.net/pull/2947
You'll need to register that serializer compat layer with JSON.NET inside Lighthouse and your .NET 4.7.1 apps.
If this issue happens during deserialization in .NET Framework application and you can't do anything about the JSON you receive, then you can extend DefaultSerializationBinder and use it in JsonSerializerSettings to deserialize JSON generated by .NET Core application:
internal sealed class DotNetCompatibleSerializationBinder : DefaultSerializationBinder
{
private const string CoreLibAssembly = "System.Private.CoreLib";
private const string MscorlibAssembly = "mscorlib";
public override Type BindToType(string assemblyName, string typeName)
{
if (assemblyName == CoreLibAssembly)
{
assemblyName = MscorlibAssembly;
typeName = typeName.Replace(CoreLibAssembly, MscorlibAssembly);
}
return base.BindToType(assemblyName, typeName);
}
}
and then:
var settings = new JsonSerializerSettings()
{
SerializationBinder = new DotNetCompatibleSerializationBinder()
};
for the base Type try to use
serializer.TypeNameHandling = TypeNameHandling.Auto
can ignore the System.Private.CoreLib namespace in Json

System.XML on XAMARIN forms project

I am trying to use XmlDocument class **
and **XmlDocument .Load(..) function
on the Portable Project of XAMARIN.Forms Portable solution with visual studio community.
The compiler says that "The type or namespace name 'XmlDocument' could not be found (are you missing a using directive or an assembly reference?"
If i go in References it don't allow me to add the System.XML namespace (there is no) and if i browse file and go to system.xml.dll it says me that the file could not be added because this component is already automatically referenced by build system.
what i can to do to use the class??
NOTE:
in .Droid and .IOS project there is a referenc to System.xml and in those projects I can use XmlDocument class.
PCL doesn't support XmlDocument. You can use System.Xml.Linq.XDocument instead.
The XmlDocument class is not available for use in a PCL library, as you can see on its documentation page under Version Information. (Compare to the Version Information section of the XmlDictionary class - notice how this class has Portable Class Library available while XmlDocument does not.)
If you want to use an XmlDocument, you'll have to create a dependency service and implement it separately under both Android and iOS versions.
I had no trouble adding XML to my project:
using System.Xml;
using System.Xml.Serialization;
public string ToXML(Object oObject)
{
XmlDocument xmlDoc = new XmlDocument();
XmlSerializer xmlSerializer = new XmlSerializer(oObject.GetType());
using (MemoryStream xmlStream = new MemoryStream())
{
xmlSerializer.Serialize(xmlStream, oObject);
xmlStream.Position = 0;
xmlDoc.Load(xmlStream);
return xmlDoc.InnerXml;
}
}
After that the XML string can be shared:
public MvxCommand ShareWaypoints => new MvxCommand(ShareWaypointsAsync);
public async void ShareWaypointsAsync()
{
try
{
string strXML = "";
foreach (var wp in waypoints)
{
strXML += ToXML(wp);
}
if (strXML != "")
await Share.RequestAsync(new ShareTextRequest
{
Text = strXML,
Title = "Share Text"
});
}
catch (Exception ex)
{
await _userDialogs.AlertAsync(ex.Message);
}
}

JSON deserialization into List<string>

I guess this is easy, but I am new and cannot find a fast answer to this:
I want to obtain a list of file names (List<string>) in a .Net 2.0 desktop app, using WebClient requesting to a WebAPI REST service.
So, I have this code in the desktop app:
using (var client = new WebClient())
{
client.Headers[HttpRequestHeader.Accept] = "application/json";
var resultString = client.DownloadString("http://localhost:3788/api/file?src=X&dest=Y");
}
and a WebAPI action like this in the service:
public IEnumerable<string> GetFiles([FromUri]string src, [FromUri]string dest)
{
// some code here
}
How would I convert the resultString, which is a JSON String, to a List<String> ?
Do I have to use JsonDataContractSerializer?
Look at this SO question and answer. The code there outlines what you would do. The key is to reference the Newtonsoft.Json namespace (add it from a NuGet package) and use the DeserializeObject generic method. The answer shows other things you can do with results.

Categories