Parsing json. Field could be plain text and object - c#

Shortly, I'm trying to create some web-API-application and I'm parsing telegram data and I am faced up with a problem.
When I get all the JSON, I see that the program can't parse it because some field(text) couldn't resolve the object(code snip below). I'm thinking about creating a custom JSON converter(that's annoying, so that's the reason why I'm here), but maybe I just don't know how to do it correctly.
Here are examples:
{
"text": "SOME VERY VERY VERY PRIVATE INFORMATION",
},
AND
{
"text": [
{
"type": "link",
"text": "SOME VERY VERY VERY PRIVATE LINK :D(probably, onlyfans)"
}
],
}

I usually use a JsonConstructor in this case. You don't need to pass all properties into the constructor, you can pass only the properties that cause a problem.
using Newtonsoft.Json;
Data data = JsonConvert.DeserializeObject<Data>(json);
public class Data
{
public List<Text> text { get; set; }
[JsonConstructor]
public Data(JToken text)
{
if (text.Type == JTokenType.String)
this.text = new List<Text> { new Text { text = (string)text } };
else this.text = text.ToObject<List<Text>>();
}
}
public class Text
{
public string type { get; set; }
public string text { get; set; }
}

I would use system.text.json More info here
and here
public class Data
{
[JsonPropertyName("text")]
public IEnumerable<TextInformation> TextInformations{ get; set; }
}
public class TextInformation
{
[JsonPropertyName("type")]
public string Type { get; set; }
[JsonPropertyName("text")]
public string Text { get; set; }
}
and use it like this
var text = JsonSerializer.Deserialize<Data>(jsonString)

Related

Deserialize issue in C# Json

PageParameters have dynamic values. I tried to add it like below.
{
"Message": [
{
"TextMessage": "Hello World",
"Notification": [{
"Page": "Order",
"OpenPage": true,
"PageParameters":[ {"filedName": "400","filedvalue": "test","test": "444"}]
} ]
}
]
}
C# Code
var notification = notificationRequest?.NotificationMessage[0].ToString();
var NotificationObj = JsonConvert.DeserializeObject<NotificationObj>(notification);
public class NotificationObj
{
public string TextMessage { get; set; }
public string AppName { get; set; }
public List<Notifications> Notification { get; set; }
}
public class Notifications
{
public string PageName { get; set; }
public bool OpenPage { get; set; }
public List<PageParameter> PageParameters { get; set; }
}
public class PageParameter
{
List<string> PageParameters = new List<string>();
}
My PageParameter have dynamic values. Its getting multiple values. So i tried to add it as a List. But its not adding values when Deserialize Json. Other values are adding. Please help to solve this.
Check my answer here. You essentially need to apply that on your PageParameter class
PageParameters is an array of Key-value pairs, which would require the use of a Dictionary in C#.
Update PageParameter to the following and re-run your deserialization:
public class PageParameter
{
Dictionary<string, string> PageParameters = new Dictionary<string, string>();
}

Return JSON from API method

I am using ASP.net Core web api (c#) here
I have a JSON string as:
{
"userId":321,
"account":"new
"fname":"Adam",
"lname":"Silver"
"features":[
{
"available":true,
"status":open,
"admin":false
}
]
}
I want to test this data in my angular code so wanted to hardcode this into my API; then I want my API to return this back. What I am finding it hard is how to return this. Shall I return this as a string or need to parse it?
I have this method in my API:
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
return new string[] { "value1", "value2" };
}
Do I need to represent this into string or parse it someway?
Your JSON is invalid. We need to correct it. JSONLint can be helpful for that. I took your JSON and corrected the syntax errors until I got this:
{
"userId": 321,
"account": "new",
"fname": "Adam",
"lname": "Silver",
"features":[
{
"available": true,
"status": "open",
"admin": false
}
]
}
Then I need to generate a C# class structure to represent this JSON. I could manually create it, but the excellent json2csharp.com can generate it for me quickly. I fed this JSON into and received the following classes back:
public class Feature
{
public bool available { get; set; }
public string status { get; set; }
public bool admin { get; set; }
}
public class RootObject
{
public int userId { get; set; }
public string account { get; set; }
public string fname { get; set; }
public string lname { get; set; }
public List<Feature> features { get; set; }
}
I put these class definitions into my application. Then I need to modify my action method to create an instance of this RootObject class (you should change the name to actually match what it's intended for).
[HttpGet]
public ActionResult<RootObject> Get()
{
// Create an instance of our RootObject and set the properties
var myRootObject = new RootObject();
myRootObject.userId = 321;
myRootObject.account = "new";
myRootObject.fname = "Adam";
myRootObject.lname = "Silver";
myRootObject.features = new List<Feature>();
// Create an instance of a feature and set its properties
var feature = new Feature();
feature.available = true;
feature.status = "open";
feature.admin = false;
// Add the new feature to the features collection of our RootObject
myRootObject.features.Add(feature);
// Return the instance of our RootObject
// The framework will handle serializing it to JSON for us
return myRootObject;
}
Note that I changed the signature of your method. I made it no longer accept an IEnumerable because it wasn't clear why you had that. And I changed it to return an ActionResult after checking Microsoft's documentation.
Hi Please find correct JSON format for above one:
{
"userId": 321,
"account": "new",
"fname": "Adam",
"lname": "Silver",
"features": [{
"available": true,
"status": "open",
"admin": false
}]
}
you can use below class in your web API to pass respective data
public class Feature
{
public bool available { get; set; }
public string status { get; set; }
public bool admin { get; set; }
}
public class RootObject
{
public int userId { get; set; }
public string account { get; set; }
public string fname { get; set; }
public string lname { get; set; }
public List<Feature> features { get; set; }
}
then at the end, while returning data, convert the respective class object into JSON by serializing that into JSON format.
Hope it will fulfill your requirement.
Putting the comments into an answer:
If you are using ActionResult, I'll assume you are using asp.net mvc. What you want is JsonResult.
[HttpGet]
public JsonResult Get()
{
return new JsonResult
{
Data = new
{
userId = 321,
account = new
{
fname = "Adam",
lname = "Silver",
features = new object[]{
new
{
available = true,
status = "open",
admin = false
}
}
}
},
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
}

c# data pull from json - can not detect the "-" sign between words

string json_index = '"libraries": [
{
"name": "test1",
"natives": {
"windows": "natives-windows"
},
"downloads": {
"classifiers": {
"natives-windows": {
"url": "http://test1.com/"
}
}
}
},
{
"name": "test2",
"natives": {
"windows": "natives-windows"
},
"downloads": {
"classifiers": {
"natives-windows": {
"url": "http://test2.com/"
}
}
}
}
]';
dynamic jsonObj = JsonConvert.DeserializeObject(json_index);
foreach (var obj in jsonObj.libraries)
{
label1.Text += "\n" + obj.downloads.classifiers.natives-windows.url; // error here
}
Can not detect the "-" sign between words.
I actually thought that:
string nativeswindows = obj.natives.windows;
label1.Text += "\n" + obj.downloads.classifiers.nativeswindows.url;
but it did not work
How can I get the "url" in "natives-windows" ?
I am using Newtonsoft JSON.
you try:
label1.Text += "\n" + obj.downloads.classifiers["natives-windows"].url;
I found this link: Parsing JSON w/ # at sign symbol in it (arobase)
Hope it will help you!
So there's a few steps to this.
First you need to define a concrete class to represent your JSON. I've done this using http://json2csharp.com, with the output being here:
public class Natives
{
public string windows { get; set; }
}
public class NativesWindows
{
public string url { get; set; }
}
public class Classifiers
{
public NativesWindows __invalid_name__natives-windows { get; set; }
}
public class Downloads
{
public Classifiers classifiers { get; set; }
}
public class Library
{
public string name { get; set; }
public Natives natives { get; set; }
public Downloads downloads { get; set; }
}
public class RootObject
{
public List<Library> libraries { get; set; }
}
Your problematic field has been flagged up by this tool too, seen here:
public NativesWindows __invalid_name__natives-windows { get; set; }
So we need a way to assign the JSON Key/Value pair to a valid C# field. We can does this using Attributes.
For this field in particular, we can use the JsonProperty attribute to take in the JSON property name and assign it to a C# field on your new concrete class. This looks like:
[JsonProperty("native-windows")]
public NativesWindows NativeWindowsObj { get; set; }
You can put that into your new concrete class, and then use the following to deserialize to that type:
Natives jsonObj = JsonConvert.DeserializeObject<Natives>(json_index);
This is telling Newtonsoft:
I have a property name native-windows.
I'm deserializing my JSON to this specific class.
The invalid C# identified native-windows matches a JsonProperty I've specified in my class, assign the value to that matching attribute.
Return the full, deserialized object.

Deserialize nested JSON into Dictionary, string and class

I have a JSON that I'd like to DeserializeObject into an outerDictionary with innerDictionary and innermostClass as so:
var entityMap = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, fieldClass>>>(File.ReadAllText("map.json"));
However, the innerDictionary may have a string:string instead of string:innerMostClass.
{
"Client": {
"__class__": "contact",
"ClientId": {
"__field__": "new_ndisclientid",
"__type__": "string"
},
"GivenName": {
"__field__": "firstname",
"__type__": "string"
},
},
"Case": {
"__class__": "contact",
"CaseId": {
"__field__": "new_ndiscaseid",
"__type__": "string"
}
}
}
Is there a way to do this? I don't want to make all of it into Classes.
Is it possible to do this with a custom JsonConverter?
EDIT: Renamed classname to entityName for clarity. ClientId and GivenName would be deserialized into fieldClasses.
You can use dynamic or object instead of inner class
var json =
"{\r\n\t\"Client\": {\r\n\t\t\"__entityName__\": \"contact\",\r\n\r\n\t\t\"ClientId\": {\r\n\t\t\t\"__field__\": \"new_ndisclientid\",\r\n\t\t\t\"__type__\": \"string\"\r\n\t\t},\r\n\t\t\"GivenName\": {\r\n\t\t\t\"__field__\": \"firstname\",\r\n\t\t\t\"__type__\": \"string\"\r\n\t\t}\r\n\t}\r\n}";
var deserialized = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, dynamic>>>(json);
List<object> values = deserialized.SelectMany(result => result.Value).Cast<object>().ToList();
If you want separate inner class
public class Client
{
public string __entityName__ { get; set; }
public Dictionary<string, string> ClientId { get; set; }
public Dictionary<string, string> GivenName { get; set; }
}
var deserializedWithClass = JsonConvert.DeserializeObject<Dictionary<string, Client>>(json);
Deserialize nested JSON into Class. not on dictionary based but it's useful.
Step 01: open the link https://jsonformatter.org/json-parser
Step 02: copy the down contents.
{
"Client": {
"__class__": "contact",
"ClientId": {
"__field__": "new_ndisclientid",
"__type__": "string"
},
"GivenName": {
"__field__": "firstname",
"__type__": "string"
}
},
"Case": {
"__class__": "contact",
"CaseId": {
"__field__": "new_ndiscaseid",
"__type__": "string"
}
}
}
Step 03: Open above link. copy contents and past in to left side and click on to JSON Parser button. Look like below image.
Step 04: Click on download button. Downloading the jsonformatter.txt file. Successfully download the file as jsonformatter.txt.
Step 05: Copy step 02 content and open url https://json2csharp.com/.Copy contents and past in to left side and click on to Convert button. Look like below image.
Step 06: In Scripting.
(A) Create myRootClass.cs file and copy and past down contents to your file.[[System.Serializable] it's used in unity 3d software c# scripting]
[System.Serializable]
public class myRootClass
{
[System.Serializable]
public class ClientId
{
public string __field__ { get; set; }
public string __type__ { get; set; }
}
[System.Serializable]
public class GivenName
{
public string __field__ { get; set; }
public string __type__ { get; set; }
}
[System.Serializable]
public class Client
{
public string __class__ { get; set; }
public ClientId ClientId { get; set; }
public GivenName GivenName { get; set; }
}
[System.Serializable]
public class CaseId
{
public string __field__ { get; set; }
public string __type__ { get; set; }
}
[System.Serializable]
public class Case
{
public string __class__ { get; set; }
public CaseId CaseId { get; set; }
}
[System.Serializable]
public class Root
{
public Client Client { get; set; }
public Case Case { get; set; }
}
}
(B) Read the jsonformatter.txt file.
// Read entire text file content in one string
string textFilePath = "C:/Users/XXX/Downloads/jsonformatter.txt";//change path
string jsontext = System.IO.File.ReadAllText(textFilePath);
Debug.Log("Read Json"+jsontext);// used Console.Writeline
(C) Convert string into C# and show the data.
Root myDeserializedClass = JsonConvert.DeserializeObject<Root>(jsontext);
var client = myDeserializedClass.Client;
Debug.Log("client.__class__ :- "+client.__class__); //used Console.Writeline
Debug.Log("client.ClientId.__field__ :- "+client.ClientId.__field__);// used Console.Writeline
Debug.Log("client.GivenName.__field__ :- "+client.GivenName.__field__);// used Console.Writeline

Cannot deserialize the JSON array

I have Json like below:
[
{
"name": "ts.DatumVon",
"value": "29.10.2015"
},
{
"name": "ts.Von",
"value": "8:00"
},
{
"name": "ts.Bis",
"value": "16:30"
}
]
for this class:
public class TSInfo
{
public TimeSaver ts { get; set; }
[Display(Name = "Status")]
public TSStatus tsStatus { get; set; }
[Display(Name = "Typ")]
public TSTyp tsTyp { get; set; }
public TSAuswahlSteps step { get; set; }
}
How to deserialize this Json string in controller method?
EDIT:
I hope that clarifies it.
public class TimeSaver
{
public DateTime DatumVon { get; set; }
public TimeSpan Von { get; set; }
public TimeSpan Bis { get; set; }
}
I tried something like this:
string tsi = [{"name":"ts.DatumVon","value":"29.10.2015"},{"name":"ts.Von","value":"8:00"},{"name":"ts.Bis","value":"16:30"}]
var dict = JsonConvert.DeserializeObject<List<Dictionary<String,String>>(tsi);
The JSON you provided is a list of dictionaries. So you can deserialize it (using NewtonSoft.Json) like this:
string json = "your json";
var result = JsonConvert.Deserialize<List<Dictionary<String,String>>(json);
How you map the result to your class is up to you.
EDIT the above makes no sense. Sorry for that.
Well, your JSON gave me some headache but I think I fixed it.
The JSON is an array of KeyValuePairs. Every pair describes an attribute of your TimeSaver class. The array as an whole describes the complete class. I don't know of an easy way to convert this JSON to a C# class. What complicates the problem even more is the fact that every attribute has some sort of namespace prefix: ts. The final complication is the date format. That's not a format that's recognized automatically.
My solution converts the JSON to a new JSON describing a TimeSaver object. This new JSON is then deserialized using JsonConvert.
One issue still remains: the TimeSaver.DateVon has become a string.
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
public class Program
{
public static void Main()
{
string tsi = "[{\"name\":\"ts.DatumVon\",\"value\":\"29.10.2015\"},{\"name\":\"ts.Von\",\"value\":\"8:00\"},{\"name\":\"ts.Bis\",\"value\":\"16:30\"}]";
var attributes = JsonConvert.DeserializeObject<List<NameValuePair>>(tsi);
attributes = attributes
.Select(item => new NameValuePair { Name = item.Name.Replace("ts.", ""), Value = item.Value })
.ToList();
var newJson = "{" + String.Join(",", attributes.Select(item => String.Format("\"{0}\":\"{1}\"", item.Name, item.Value))) + "}";
Console.WriteLine(newJson);
var ts = JsonConvert.DeserializeObject<TimeSaver>(newJson);
Console.WriteLine(ts.DatumVon);
Console.WriteLine(ts.Von);
Console.WriteLine(ts.Bis);
}
}
public class NameValuePair
{
public string Name { get; set; }
public string Value { get; set; }
}
public class TimeSaver
{
public String DatumVon { get; set; }
public TimeSpan Von { get; set; }
public TimeSpan Bis { get; set; }
}

Categories