How to parse json object with variable key names using DataContractJsonSerializer - c#

I intend to use DataContractJsonSerializer to convert the json i'm receiving to an object, but the keys in the root can have any name, something similar to this:
{
"Jhon": {...},
"Lucy": {...},
"Robert": {...}
...
}
When the keys are fixed i can use [DataMember(Name = "keyname")] but in this case I don't know what to do. Any ideas?

Try this:
var serializer = new DataContractJsonSerializer(typeof(RootObject), new DataContractJsonSerializerSettings()
{
UseSimpleDictionaryFormat = true
});
var json = #"{
""Jhon"": { ""Name"": ""John""},
""Lucy"": {},
""Robert"": {}
}";
var bytes = Encoding.UTF8.GetBytes(json);
using (var stream = new MemoryStream(bytes))
{
var results = serializer.ReadObject(stream);
}
// Define other methods and classes here
public class RootObject : Dictionary<string, User>
{
}
public class User
{
public string Name { get; set; }
}

Related

How to set json field name from property value in run-time .net

How to serialize an object to json through setting json field name from object's property value?
I am using NewtonsoftJson as a json library.
public class Data
{
public string Question {get;set;} = "Test Question?";
public string Answer {get;set;} = "5";
}
expected json output:
{
"Test Question?": {
"Answer": "5"
}
}
You can use a dictionary for that:
JsonSerializer.Serialize(
new Dictionary<string, object>
{
{
data.Question, new
{
data.Answer
}
}
});
or if you are using Newtonsoft, you can use the
JsonConvert.SerializeObject method for serialization, with the same input.
Just for a record
var data = new Data();
string json = new JObject { [data.Question] = new JObject { ["Answer"] = data.Answer } }.ToString();

Turn object from API to string C#

I am doing a bot for VK on C# and faced to some problems. I have method which returns JSON like this
{
"ts": 1674111105,
"updates": [[4,
2262,
17,
61835649,
1534493714,
"",
{
"attach1_type": "doc",
"attach1": "61835649_472186415",
"title": " ... "
}
]]
}
This is object, as I see, but I cant get anything from the attach_type1 to title including. This is also an object, and it can't be transformed to string just like .ToString(), because in that case in the result I have System.Object. So, does anybody know how I can change this type or is it impossible?? I am in desperation.
I created a class for this object
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.Serialization;
namespace CSharpVKbot.VK.UserLongPoll
{
[DataContract()]
public class Attachment
{
[DataMember(Name = "attach1_type")]
public string AttachType;
[DataMember(Name = "attach1")]
public string Attach;
[DataMember(Name = "title")]
public string Title;
}
}
created an object of this class
public Attachment DocId = new Attachment();
and then tried to change type to attachment, but it doesnt work either
case UpdateCode.NewMessage:
u.MessageID = (int)item[1];
u.Flags = (int)item[2];
u.PeerID = (int)item[3];
u.TimeStamp = (int)item[4];
u.Text = (string)item[5];
u.DocId = (Attachment)item[6];
break;
You need to deserialise the JSON - It cannot be just converted to an object.
Try something like
Attachment deserializedAttachement = new Attachment();
MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(item[6]));
DataContractJsonSerializer ser = new DataContractJsonSerializer(deserializedAttachment.GetType());
deserializedAttachment = ser.ReadObject(ms) as Attachment;
ms.Close();
Where item[6] is the string that represents the attachment information.
See - https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-serialize-and-deserialize-json-data#example
I think that you will have to iterate through all json properties.
This code may help you
dynamic obj = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(YourJsonString);
foreach (var prop in obj)
{
if (prop is Newtonsoft.Json.Linq.JObject)
{
// Handle JObject
}
if (prop is Newtonsoft.Json.Linq.JProperty)
{
// Handle JProperty
}
}
There are many direction to resolve your problem.
I like it (using Newtonsoft):
JObject data = (JObject)JsonConvert.DeserializeObject(json);
var attach1_type = data.Descendants()
.OfType<JProperty>()
.FirstOrDefault(x => x.Name == "attach1_type")
?.Value;
numbers, strings, objects are in same array, which means they are boxed before returning to you. so your updates is List<List<object>> or object[][], whatever. your c# class, which match this json format, could be simply like this:
public class SomethingJsonResult
{
public int ts { get; set; }
public List<List<object>> updates { get; set; }
}
The 1st option is to use anonymous type:
public void ParseJsonResult(SomethingJsonResult result)
{
var definition = new
{
attach1_type = "",
attach1 = "",
title = ""
};
result?.updates?.ForEach(x =>
{
var update = JsonConvert.DeserializeAnonymousType(x[6], definition);
var attachment = new Attachment
{
AttachType = update.attach1_type,
Attach = update.attach1,
Title = update.title,
};
});
}
The 2nd option is a bit complex:
[DataContract()]
public class Attachment
{
[DataMember(Name = "attach1_type")]
[JsonProperty("attach1_type")] //Tell JsonConverter how to map your object
public string AttachType { get; set; }//Here is property, but not variable
[DataMember(Name = "attach1")]
[JsonProperty("attach1")]
public string Attach { get; set; }
[DataMember(Name = "title")]
[JsonProperty("title")]
public string Title { get; set; }
}
public void ParseJsonResult(SomethingJsonResult result)
{
result?.updates?.ForEach(update =>
{
//(Attachment)update[6] works only when your names of properties 100% match json objects
JsonConvert.DeserializeObject<Attachment>(update[6])
....
});
}
DataContractSerializer example:
https://learn.microsoft.com/en-us/dotnet/api/system.runtime.serialization.datamemberattribute?redirectedfrom=MSDN&view=netframework-4.7.2
you can implement everything inside your custom converter:
https://www.newtonsoft.com/json/help/html/CustomJsonConverter.htm
JsonConvert.DeserializeObject<AttachmentWrapper>(json, new AttachmentConverter(typeof(AttachmentWrapper)));

converting Json data to c# understandable format

I am trying to convert my json data to c sharp understandable format so that I can use JsonConvert.SerializeObject to convert that data to JSON format and send it over HTTP protocol. My json data is as follows:
{
"m2m:ae":
{
"api": "ADN_AE_ATCARD06",
"rr": "true",
"lbl": ["AT06"],
"rn": " adn-ae_AT06"
}
}
I tried to write it in c sharp understandable format but was able to do this:
var obj = new
{
m2m = new
{
api = "ADN_AE45",
rr = "true",
lbl = new[] { "ad" },
rn = "adfrt"
}
};
var result = JsonConvert.SerializeObject(obj, Formatting.Indented);
my issue is how to include m2m:ae into my c-sharp code. I am new to json, I am able to convert only if parent object has no value but if it has value I am not able to. please help.
I was incorrect in my comment. While "m2m:ae" is not a valid name for a C# property is valid JSON. This can be accomplished by tagging the class property with JsonProperty.
Define your class like this
public class TestJson
{
[JsonProperty("m2m:ae")]
public Class2 Class2Instance { get; set; }
}
public class Class2
{
public string Api { get; set; }
public string Rr { get; set; }
public string[] Lbl { get; set; }
public string Rn { get; set; }
}
and then populate your class like this
_sut = new TestJson
{
Class2Instance = new Class2 {Api = "ADN_AE45", Rr = "true", Lbl = new[] {"ad"}, Rn = "adfrt"}
};
and serialize
_result = JsonConvert.SerializeObject(_sut, new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
});
The resulting serialized object looks like
{
"m2m:ae": {
"api": "ADN_AE45",
"rr": "true",
"lbl": ["ad"],
"rn": "adfrt"
}
}
and deserialization is the reverse
var test = JsonConvert.DeserializeObject<TestJson>(_result, new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
});
Did you write the Json in a text file?
If yeah so fileTxt is what is written on the file(as json)
String fileTxt = File.ReadAllText(Give a path for a file); //read from file
Jobject Json = Jobject.Parse(fileTxt); //convert the string to Json
Console.WriteLine($"rr: {Json["rr"]} "); // get the rr from json and print it
Other than class method mentioned by Fran one can use the Dictionary method to create key value pair and newtonsoft.json library to convert to json.
var sub= Dictionary<string,string>
{{"abc","xyz"}
};
var main = Dictionary<string,object>
{{"wer:asd",sub}
};
string str= JsonConvert.SerializeObject(main);

How do you serialize non-standard JSON with JSON.net? [duplicate]

I have to read a JSON stream (which I have no control over), which is in the form:
{"files":
{
"/some_file_path.ext": {"size":"1000", "data":"xxx", "data2":"yyy"},
"/other_file_path.ext": {"size":"2000", "data":"xxx", "data2":"yyy"},
"/another_file_path.ext": {"size":"3000", "data":"xxx", "data2":"yyy"},
}
}
So, I have an object named files, which has a number of properties, which have 1) different names every time, 2) different number of them every time, and 3) names with characters which can't be used in C# properties.
How do I deserialize this?
I'm putting this into a Portable Library, so I can't use the JavaScriptSerializer, in System.Web.Script.Serialization, and I'm not sure about JSON.NET. I was hoping to use the standard DataContractJsonSerializer.
UPDATE: I've changed the sample data to be closer to the actual data, and corrected the JSON syntax in the area the wasn't important. (Still simplified quite a bit, but the other parts are fairly standard)
You can model your "files" object as a Dictionary keyed by the JSON property name:
public class RootObject
{
public Dictionary<string, PathData> files { get; set; }
}
public class PathData
{
public int size { get; set; }
public string data { get; set; }
public string data2 { get; set; }
}
Then, only if you are using .Net 4.5 or later, you can deserialize using DataContractJsonSerializer, but you must first set DataContractJsonSerializerSettings.UseSimpleDictionaryFormat = true:
var settings = new DataContractJsonSerializerSettings { UseSimpleDictionaryFormat = true };
var root = DataContractJsonSerializerHelper.GetObject<RootObject>(jsonString, settings);
With the helper method:
public static class DataContractJsonSerializerHelper
{
public static T GetObject<T>(string json, DataContractJsonSerializer serializer = null)
{
using (var stream = GenerateStreamFromString(json))
{
var obj = (serializer ?? new DataContractJsonSerializer(typeof(T))).ReadObject(stream);
return (T)obj;
}
}
public static T GetObject<T>(string json, DataContractJsonSerializerSettings settings)
{
return GetObject<T>(json, new DataContractJsonSerializer(typeof(T), settings));
}
private static MemoryStream GenerateStreamFromString(string value)
{
return new MemoryStream(Encoding.Unicode.GetBytes(value ?? ""));
}
}
Alternatively, you can install Json.NET and do:
var root = JsonConvert.DeserializeObject<RootObject>(jsonString);
Json.NET automatically serializes dictionaries to JSON objects without needing to change settings.
We need to first convert this Invalid JSON to a Valid JSON. So a Valid JSON should look like this
{
"files":
{
"FilePath" : "C:\\some\\file\\path",
"FileData" : {
"size": 1000,
"data": "xxx",
"data2": "yyy"
},
"FilePath" :"C:\\other\\file\\path",
"FileData" : {
"size": 2000,
"data": "xxx",
"data2": "yyy"
},
"FilePath" :"C:\\another\\file\\path",
"FileData" : {
"size": 3000,
"data": "xxx",
"data2": "yyy"
}
}
}
To make it a valid JSON we might use some string functions to make it looks like above. Such as
MyJSON = MyJSON.Replace("\\", "\\\\");
MyJSON = MyJSON.Replace("files", "\"files\"");
MyJSON = MyJSON.Replace("data:", "\"data:\"");
MyJSON = MyJSON.Replace("data2", "\"data2\"");
MyJSON = MyJSON.Replace(": {size", ",\"FileData\" : {\"size\"");
MyJSON = MyJSON.Replace("C:", "\"FilePath\" :\"C:");
Than we can create a class like below to read the
public class FileData
{
public int size { get; set; }
public string data { get; set; }
public string data2 { get; set; }
}
public class Files
{
public string FilePath { get; set; }
public FileData FileData { get; set; }
}
public class RootObject
{
public Files files { get; set; }
}
Assuming you have a valid JSON you could use JavaScriptSerializer to return a list of objects
string json = "{}"
var serializer = new JavaScriptSerializer();
var deserializedValues = (Dictionary<string, object>)serializer.Deserialize(json, typeof(object));
Alternatively you could specify Dictionary<string, List<string>> as the type argument
strign json = "{}";
JavaScriptSerializer serializer = new JavaScriptSerializer();
var deserializedValues = serializer.Deserialize<Dictionary<string, List<string>>>(json);
foreach (KeyValuePair<string, List<string>> kvp in deserializedValues)
{
Console.WriteLine(kvp.Key + ": " + string.Join(",", kvp.Value));
}

Create a json request object in c#

[{
"channel_id":299,
"requests":[{
"order_id":3975,
"action":"REQUEST_LABELS"
}]
}]
How to create the above request in c# the requests can be multiple.
I am new to c# i tried the below:
Dictionary<long, List<object>> requestObject = new Dictionary<long, List<object>>();
List<object> listrequestObjects = new List<object>();
Request requestOb = new Request();
requestOb.order_id = 2372;
requestOb.action = "REQUEST_LABELS";
listrequestObjects.Add(requestOb);
requestObject.Add(2352635, listrequestObjects);
string requesttest = JsonConvert.SerializeObject(requestObject);
But getting a weird request. Please help.
The structure should look like :
public class Request
{
public int order_id { get; set; }
public string action { get; set; }
}
public class RootObject
{
public int channel_id { get; set; }
public List<Request> requests { get; set; }
}
You need to declare the root object also:
[Serializable]
public class Root {
public int channel_id;
public Request[] requests;
}
Then assign the value and serialize it:
var root = new Root();
root.channel_id = 299;
root.requests = listrequestObjects.ToArray();
string requesttest = JsonConvert.SerializeObject(root);
You can use Newtonsoft.Json.
try this
private JArray GetResponse()
{
var main_array = new JArray();
var channel_id = new JObject();
channel_id.Add("channel_id",299);
var request = new JArray();
var order_id = new JObject();
order_id.Add("order_id",3975);
var action = new JObject();
action.Add("action","REQUEST_LABELS");
request.Add(order_id);
request.Add(action);
main_array.Add(channel_id);
main_array.Add(request);
return main_array;
}
Please try the JavaScriptSerializer class available in namespace
using System.Web.Script.Serialization
JavaScriptSerializer js = new JavaScriptSerializer();
string result = js.Serialize(requestObject);
The requestObject list is your custom class with all necessary properties.
Thanks

Categories