I am using a 3rd party server that exposes an API via REST(so it is not possible to change the JSON). The JSON it returns is in a format like:
[
{
"#noun":"tag",
"#version":0,
"#tag":"myFoo"
}
]
I created a C# object to represent this item
public class ResponseItem
{
public string noun {get;set;}
.....
}
however, when I try to use the JavaScriptSerializer to deserialize this object, the properties do NOT get assigned. The serializer seems to be unable to handle the properties with the # symbol in front of the name.
Any ideas on how to solve this?
Ok, so after some finagling, I ditched the JavaScriptSerializer. I switched over to the DataContractJsonSerializer. I then use well defined data contracts and use the DataMember attribute to specify the name.
i.e.
[DataContract]
public class ResponseItem
{
[DataMember(Name="#noun")]
public string Noun {get;set;}
....
}
There may be a better/different way, but this works and is an acceptable solution
Related
I am trying to get around that C# prefers to have classes generated (I know they are easy to generate, but currently my format and parameters are changing a lot due to development in both client and server end).
Example of what I most often find when I try to find out to deserialize is that you first have to know the exact structure - then build a class - and then you can refer to it later on (it's fine, but it's just not what I would like to do):
Json format 1:
[{"FirstName":"Bob","LastName":"Johnson"},{"FirstName":"Dan","LastName":"Rather"}]
public class People
{
public string FirstName { get; set; }
public string LastName { get; set;}
}
public List<People> peopleList;
. . . // (same as first example)
//Change the deserialize code to type <List<Class>>
peopleList = deserial.Deserialize<List<People>>(response);
That of course is easy as long as the reply doesn't change format, if for example the reply changes to a nested field :
Json format 2:
[{"FirstName":"Bob","LastName":"Johnson"},{"data":{"nestedfield1"
:"ewr"} }]
I would of course have to change the class to represent that, but at the moment we are moving back and forth in formats and I would somehow like if there was a way where I could try to access json elements directly in the string?
For example, like I can do in Python:
mystring1 = reply ["firstName"] mystring2 = reply ["data"]["nestedfield1"]
Is there any way to achieve this in C#? It would speed up development rapidly if there was a way of accessing it without first referencing the output in the code to then once again reference the class variable that was created when referencing it.
And note it's for rapid development, not necessarily for the final implementation where I can see advantages by doing the class approach.
Another way of asking was maybe can it serialize taking any format (as long as its JSON) and dynamically build up a struct where I can access it with named keys and not as class variables?
to deserialize json without using classes you can use using Newtonsoft.Json
here's the code:
using System;
using Newtonsoft.Json;
using System.Text;
public class Program
{
public static void Main()
{
var myJSONString = "[{\"FirstName\":\"Bob\",\"LastName\":\"Johnson\"},{\"FirstName\":\"Dan\",\"LastName\":\"Rather\"}]";
dynamic obj = JsonConvert.DeserializeObject<dynamic>(myJSONString);
Console.WriteLine(obj[0].FirstName);
}
}
The obj will perform the same way you use when generating classes,
it can take any json string and deserialize into dynamic object regardless of structure of the json. Keep in mind that you won't get VS intellisense support.
UPDATE
Here's fiddle:
https://dotnetfiddle.net/xeLDpK
When I use eaz and newtonsoft json it encrypts all my json data. Is there a way to decrypt it in c# or disable the encryption of the data?
I use virtualization and encryption with password
I talked with Eazfuscator back in 2020 and was able to integrate this using the constructor nicely.
One thing you MUST do however is use the json property name attribute as obfuscated properties will get renamed, you can't be sure what name it will get and also can't guarantee that the "next" compilation/ obfuscation generates the same name.
Anyway easy enough to fix method 1 use the names from the json to map via constructor
private class MyProprietaryData
{
internal MyProprietaryData(string a1, int a2)
{
AccountNumber=a1;
Code=a2;
}
[JsonProperty("a1")]
public string AccountNumber{get;}
[JsonProperty("a2")]
public int Code{get;}
}
method 2 use json to populate the fields and not the properties
private class MyProprietaryData
{
[JsonProperty("a1")]
string _accountNumber;
[JsonProperty("a2")]
int _code;
internal MyProprietaryData(string accountNumber, int code)
{
AccountNumber=accountNumber;
Code=code;
}
[JsonIgnore]
public string AccountNumber =>_accountNumber;
[JsonIgnore]
public int Code => _code;
}
As well as all the combinations that .net gives you, only thing you should remember is that field renaming will affect run-time generated mappers like json serialization does. This works on the new .net json as well as the newtonsoft json.
You didn't ask it but a free piece of advice, when excepting external data like with json, xml, gRPC always assume data is manipulated and validate the data, you can do this by having a checksum field that you serialize in the data and that you check, in case of json in the [jsonconstructor] annotated constructor.
I have a POCO class in C# that represents a JSON object:
class
public int id {get; set;}
public string name {get; set;}
public string description {get; set;}
JSON
{
"id" : 1,
"name" : "name",
"description" : "description"
}
Now the json is going to have these properties added:
{
"property_1" : "value_1",
"property_2" : "value_2",
"property_3" : "value_3"
//etc
}
There could be as few as 0 properties and as many as needed but they would all be named property_ and a number.
So for the class I want to have a List<> of some sort instead of hard coding each property individually, but then went returning the Json object (I'm using MVC) I want to split that List<> into individual objects, how can I do that?
Instead of having:
return Json(property_1, property_2, property_3);
I want:
return Json(properties.Split());
If you are using Json.NET for your JSON serialization, you can use the [JsonExtensionData] attribute to capture properties which you have not coded for. Starting with Json.NET 5.0.8, this property affects both serialization and deserialization to ensure your POCO objects support round-tripping.
In practice, I placed this attribute on a field in an abstract base class which all of my model classes are derived from:
ExtensibleJsonObject
You can write your own custom MediaTypeFormatter and insert it to your HttpConfiguration.Formatters collection in front of the standard JsonFormatter, or extend the standard one and replace it entirely. (I'd suggest the former.)
The MediaTypeFormatters give you access to the raw stream as it's comming in, and you can basically do whatever you want with both serialization and deserialization at that point using all of JSON.NET.
I use stock JSON serialiser in .NET 4.5 windows store app -
System.Runtime.Serialization.Json.DataContractJsonSerializer
I have a class which is supplied by the API provider say
class A { public DateTime Date {get;set} }
I wanted to hide Date field by doing this (NOTE - new keyword):
class AEx : A { public new string Date {get;set} }
But I am getting exception:
type 'AEx' is not serializable with DataContractJsonSerializer because the data member 'Date' is duplicated in its type hierarchy.
I understand what it does.. My question however is not HOW does it do but why?
Logically speaking it should be compatible with the programming features like polymorphism. Why this class was made to ignore it?
Your class basically contains two properties with the same name. So if you try to deserialize some JSON which contains that property name, there's no way of knowing which property to set.
Likewise when serializing an object of that type, you've got two values which need to be serialized using the same property name - what would you expect the JSON to look like?
Fundamentally, a type with two properties of the same name is incompatible with serialization of a plain name/value pair format. (A more advanced serialization mechanism which could specify which property was associated with which declaring class would cope, but JSON doesn't do that.)
DataContractJsonSerializer this is nice class added in the .net framework which can be used to serialize/desirealize object into JSON.
Now following is the example i am trying
[Serializable] class User { public string name; public string userId; }
Now following is the output generated
Output : Notice structure where only "name" is expected instead of k__BackingField
Now this is the problem after digging so much i am not sure from where <> and _BackingField is coming ?
{
"<name>k__BackingField":"test user",
"<userId>k__BackingField":100001}
This is just an educated guess. I think it's because you're using public fields instead of properties for name and userid.
Edit: It appears it also has to do with the fact that you are using the [Serializable] attribute instead of [DataContract] and [DataMember]. Check out this post for more detail:
C# automatic property deserialization of JSON