Get RAW Json with .NET Core Text.Json - json

I have pretty much the same question as this one:
Get Raw json string in Newtonsoft.Json Library
but now using the Text.Json.Serialization in .NET Core 3.1, I struggle to find the equivalent of JRaw.
I want to have an extensible object like:
{
"id": "myId",
"name": "name",
"description": "my description",
"extensions": {
"unit": "C°",
"minVal": "0",
"maxVal": "100",
"precision": "1",
"enum": ["str1", "str2"],
...
}
}
I want to get the Id, Name and Description set in an object, but the extensions is a bunch of properties which can be whatever. So I want to keep the RAW Json for this extensions.
public class MyData
{
public string id { get; set; }
public string name { get; set; }
public string description { get; set; }
[JsonConverter(typeof(RawJsonStringConverter))]
public string extensions { get; set; }
}
I am fighting with a custom converter as documented here:
https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-converters-how-to
I tried with string, JsonElement, object.
No success so far.
Any idea?

Using JsonElement seems to be enough, without any custom converter:
public class MyData
{
public string Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public JsonElement? Extensions { get; set; }
}
edit: JsonElement? as nullable is better: it allows JsonElement to be fully optional, if you have the corresponding settings in JsonSerializerOptions.
I am working with the following JsonSerializerOptions:
public static JsonSerializerOptions UpdateJsonSerializerOptions(this JsonSerializerOptions options, bool enumAsString = true)
{
if (options == null)
options = new JsonSerializerOptions();
options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
options.IgnoreNullValues = true;
options.WriteIndented = true;
if (enumAsString)
{
// convert enums as strings
options.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase));
}
return options;
}
IgnoreNullValues is the important part to have the proper conversion when no extensions at all in the input.
And CamelCase allows to stay with .NET property names (e.g 'Name') while the JSON will be with 'name'

Related

Deserialize complex json in C#

I have this json and need to parse the nested details. using Newtonsoft.Json for Deserializing but cant really parse this complex json.
{
"name": "John",
"email": "john#gmail.com",
"data": [
{
"company_name": "instagram",
"company_email": "abc#email.com",
"org": {
"org_name": "john-insta",
"org_dob": "1/1/1990",
}
},
{
"company_name": "google",
"company_email": "abc1#email.com",
"org": {
"org_name": "john-google",
"org_dob": "1/1/1990",
}
},
]
The number of entries in "data" may actually be varying dynamically, how do I parse the entries for company_name, company_email, org_name,org_dob.
What is the problem you are having? This seems fairly simple JSON array. Setup your classes like this.
public class MyClass
{
public string name { get; set; }
public string email { get; set; }
public List<DataClass> data { get; set; }
}
public class DataClass
{
public string company_name { get; set; }
public string company_email { get; set; }
public Org org { get; set; }
//Any other and all possible properties...
}
public class Org
{
public string org_name { get; set; }
public string org_dob { get; set; }
}
Then it can be parsed using Newtonsoft or similar using.
var test = JsonConvert.DeserializeObject<MyClass>(json);
This method also has an overload where you can pass settings to ignore nulls.
var test = JsonConvert.DeserializeObject<MyClass>(json,
new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });

Return Json Format to View - MVC

I am new to asp.net MVC. I hav to return Json from controller to view using ajax call, that is perfect.
I want to return below json format to view.
[{
"name": "A",
"data": [7.0, 6.9, 9.5, 14.5, 18.4, 21.5, 25.2, 26.5, 23.3, 18.3, 13.9, 9.6] },
{
"name": "B",
"data": [3.9, 2, 5.7, 8.5, 11.9, 15.2, 17.0, 16.6, 14.2, 10.3, 6.6, 4.8]
},
{
"name": "C",
"data": [3.9, 2, 5.7, 8.5, 11.9, 15.2, 17.0, 16.6, 14.2, 10.3, 6.6, 4.8]
}]
I have tried below modal to return such a format,
public class myModel
{
public List<string> Name { get; set; }
public List<float> Average { get; set; }
}
What should be my model like to return above mentioned format?
MyModel should be modified like this
public class MyModel
{
public string name { get; set; }
public List<float> data { get; set; }
}
as name property is only for a single string, and data is actually the array holding the float values.
You can return List<MyModel> or array - MyModel[] as JSON from ajax call
model type should be:
public class myModel
{
public string name { get; set; }
public List<float> data { get; set; }
}
AND in Controller:
List<myModel> list=new List<myModel>();
return new JsonResult()
{
Data = list,
JsonRequestBehavior = JsonRequestBehavior.AllowGet,
MaxJsonLength = Int32.MaxValue
};
public class MyModel
{
public string Name { get; set; }
public List<float> Data { get; set; }
}
public JsonResult MyMethod()
{
List<MyModel> list = new List<MyModel>();
// Do stuff
return Json(list);
}
Viewmodel:
public class ViewModel
{
public List<MyModel> myModel {get;set;}
}
myModel should be like this:
public class myModel
{
public string name { get; set; }
public IList<double> data { get; set; }
}
You can easily generate this kind of task with jsonutils online.
Your model should be like this.
public class myModel
{
public string name { get; set; }
public List<double> data { get; set; }
}
Here name contain single string value and data is contain array of double value.
Note : Use json2charp to convert your JSON to c# class type or if you are using vs2013 or above version paste copied JSON in C# class type.

Fetch JSON array using WebClient and Json.Net and display it in textview?

My Activity code is:
private void MClient_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
{
string json = Encoding.UTF8.GetString(e.Result);
var Details = JsonConvert.DeserializeObject(json);
}
My doctor.cs class code is:
namespace App12
{
public class Doctor
{
public string DoctorId { get; set; }
public string doctorName { get; set; }
public string specialityId { get; set; }
public string experiance { get; set; }
public string fee { get; set; }
}
public class RootObject
{
public Doctor doctor { get; set; }
}
}
JSON array is:
{
"0": {
"DoctorId": "1",
"doctorName": "DR.Rama",
"specialityId": "1",
"experiance": "5 years",
"fee": "300rs"
}
}
I am trying to show this in textview but it gives me an error:
System.InvalidCastException: Specified cast is not valid.
You have two problems here.
Your class structure doesn't quite match up with the shape of the JSON data. This JSON isn't technically an array either; it's a dictionary. You need to deserialize into a Dictionary<string, Doctor>.
When calling JsonConvert.DeserializeObject you need to specify a type parameter. If you don't, the return type will be JObject. This may be the cause of the InvalidCastException.
Try it like this:
var dict = JsonConvert.DeserializeObject<Dictionary<string, Doctor>>(json);
From there you can loop through the doctors like this:
foreach (var doctor in dict.Values)
{
textView.Append(doctor.doctorName);
}

Costomising the serialisation/serialised JSON in service stack

I need to turn this beutifull default JSON from Service Stack :
{
"Status": "ok",
"LanguageArray": [{
"Id": 1,
"Name": "English"
}, {
"Id": 2,
"Name": "Chinese"
}, {
"Id": 3,
"Name": "Portuguese"
}]
}
To this monstrosity of abomination:
{"status":"ok","language":{
"0":{"id":"1", "name":"English"},
"1":{"id":"2", "name":"Chinese"},
"2":{"id":"3", "name":"Portuguese"},
}
For reasons beyond my control or ration or logic.
My question is what are the simplest way of achieving this?
I need to do this to almost all Arrays ( they are IEnumerables implemented using List in C#)
I don't think I have a 'simplest way' and it kind of depends on where you need the serialization to happen as well as how strict the format is (case sensitive?, spacing?)
If place your example text and turn it into classes like this
public class Language
{
public int Id { get; set; }
public string Name { get; set; }
}
public class OuterLanguage
{
public string Status { get; set; }
public IEnumerable<Language> LanguageArray { get; set; }
}
A pretty straightforward way would be having a Dto that adds a property for serialization of the Array and ignores the original Array.
public class OuterLanguageDto
{
public string Status { get; set; }
[IgnoreDataMember]
public IEnumerable<Language> LanguageArray { get; set; }
public IDictionary<string, Language> language
{
get { return this.LanguageArray.ToDictionary(x => (x.Id - 1).ToString()); }
}
}
When you need to serialize your class (OuterLanguage) you use TranslateTo (or your preferred Mapper) and copy the values over to the Dto.
var jsonObj = obj.TranslateTo<OuterLanguageDto>();
var jsonStr = new JsonSerializer<OuterLanguageDto>().SerializeToString(jsonObj);
You could also look into Custom Serialization. That would give you to have a way to serialize all your Arrays into the correct format.
JsConfig<IEnumerable<Language>>.SerializeFn = ToJson
private string ToJson(IEnumerable<Language> arr)
{
var dict = arr.ToDictionary(x => x.Id - 1);
var str = JsonSerializer.SerializeToString<Dictionary<int, Language>>(dict);
return str;
}
However, I'm guessing you may have to do some "magic string work" to take your custom serialized Array's json string and format it properly when outer class (OuterLanguage in this example) is the one being serialized.

How to replace $ when converting JSON object to c# with out actually changing the name of that particular field in which $ exists?

When I'm converting Json objects to c#, I got an issue In which my Json has fields with $ symbol(ex: $t).But c# doesn't accept fields with special characters. If i try to replace $ with any other letters in my c# code, I'm unable to get data from 3rd party because of the change in naming.
How can I solve this issue?
Json string:
"author": [(1)
{
"name": {
"$t": "theabctv"
},-
"uri": {
$t": "http://gdata.abc.com/feeds/api/users/theabctv"
},-
"yt$userId": {
"$t": "tCUABCCT7wYG1PMCpw"
}-
}-
],-
C# code:-
public class Author2
{
public Name2 name { get; set; }
public Uri2 uri { get; set; }
public YtUserId __invalid_name__yt$userId { get; set; }
}
public class Name2
{
public string __invalid_name__$t { get; set; }
}
public class Uri2
{
public string __invalid_name__$t { get; set; }
}
public class YtUserId
{
public string __invalid_name__$t { get; set; }
}
There is no way to declare property names with symbols in NET framework, meaning that you cant have isomorphism between the JSON objects and the C# objects without parsing the JSON data. You could replace all $ symbol with any given string (carefully chosen), manage the data in the code behind and when you need to send JSON data of the object apply the inverse replacement.