Custom property name on object serialization - c#

I have data bind to an object. Now I want to serialize it with a custom property name.
[JsonProperty(PropertyName = "KLM")]
public string ABC { get; set; } = "Test1";
[JsonProperty(PropertyName = "NOP")]
public string DEF { get; set; } = "Test2";
[JsonProperty(PropertyName = "QRS")]
public string GHI { get; set; } = "Test3";
When I serialize this object I want below serialization
{ "KLM" : "Test1", "NOP" : "Test2", "QRS" : "Test3" }
instead of
{ "ABC" : "Test1", "DEF" : "Test2", "GHI" : "Test3" }
and when deserialize it with the below JSON it should work just fine
{ "ABC" : "1Test", "DEF" : "2Test", "GHI" : "3Test" }
This question might have been asked many times, but I couldn't find the appropriate answer.

Please try that:
using Newtonsoft.Json;
namespace Application.ConsoleApp
{
class Program
{
static void Main(string[] args)
{
var j = "{ \"KLM\" : \"Test1\", \"NOP\" : \"Test2\", \"QRS\" : \"Test3\" }";
var o = JsonConvert.DeserializeObject<MyJsonObject>(j);
var s = JsonConvert.SerializeObject(o);
}
}
public class MyJsonObject
{
[JsonProperty(PropertyName = "KLM")]
public string ABC { get; set; } = "Test1";
[JsonProperty(PropertyName = "NOP")]
public string DEF { get; set; } = "Test2";
[JsonProperty(PropertyName = "QRS")]
public string GHI { get; set; } = "Test3";
}
}
You might be using different tools for attributes and serialization / deserialization. In my example, you can see that I am using the Newtonsoft library. I am taking attributes and methods from this library. For example, if you use attributes from Newtonsoft and methods from System.Text.Json, it won't work the way you want.
UPD:
Isn't that what you want?
The image shows that this works both ways. If json matches attributes then it is desirialized by attributes. If json matches the names of the properties of the class, then json is deserialized by the names of the properties. This object is always desirialized by attributes.
Sorry if I still misunderstand you!

Related

How to add a property data: for json?

I've created a list of object in C# but I'm struggling to understand how I can add a property (that may not be the right term) to the beginning of it:
This might be really obvious and I'm not sure what I need to Google! Any help would be appreciated!
What I'm trying to do:
{
'data' : [ <--Add this in (is this a property of the object?)
{
'valueName1': 'value1',
'valueName2': 'value2',
'valueName3': 'value3',
},
{
'valueName1': 'value1',
'valueName2': 'value2',
'valueName3': 'value3',
},
]}
What I've got currently!
[
{
'valueName1': 'value1',
'valueName2': 'value2',
'valueName3': 'value3',
},
{
'valueName1': 'value1',
'valueName2': 'value2',
'valueName3': 'value3',
},
]
This is what I've got in C# at the moment:
result= new List<TestList> { };
foreach (var issueData2 in myDeserializedClass.issues)
{
result.Add(new TestList { valueName1 = issueData2.fields.summary,
valuename2 = issueData2.fields.created,
valuename3 = issueData2.fields.updated, });
}
string jsonString = JsonConvert.SerializeObject(newtonresult);
With this class:
public class TestList
{
public String valuename1 { get; set; }
public String valuename2 { get; set; }
public String valuename3 { get; set; }
}
Please don't violate C# naming conventions (properties have PascalCaseNames) just to get your JSON to appear correctly; common json serializers support attributes that allow you to name your C# properties differently to json:
public class TestList
{
[JsonProperty("valuename1")]
public String ValueName1 { get; set; }
[JsonProperty("valuename2")]
public String ValueName2 { get; set; }
[JsonProperty("valuename1")]
public String ValueName3 { get; set; }
}
..that's if you even need to; you can usually also configure serializers so they produce camelCaseJsonPropertyNames even if the C# names are PascalCase - for example
And as GSerg comments, you can put your testlist list in another class:
public class Wrapper {
[JsonProperty("data")]
public List<TestList> Data { get; set;}
}
Then have a creation of:
result= new List<TestList> { };
foreach (var issueData2 in myDeserializedClass.issues)
{
result.Add(new TestList { valueName1 = issueData2.fields.summary,
valuename2 = issueData2.fields.created,
valuename3 = issueData2.fields.updated, });
}
var ser = new Wrapper { Data = result };
string jsonString = JsonConvert.SerializeObject(ser);
You actually don't even need the class Wrapper, if you want.. You can also use an anonymous type:
string jsonString = JsonConvert.SerializeObject(new{ data = result });
So, you basically want property data which is an array of object TestList class
public class Test{
public IEnumerable<TestList> data {get; set'}
}
Now you can serialize the data
string jsonString = JsonConvert.SerializeObject<Test>(newtonresult);

Parse Json works partly - empty sub object

I want to parse a json file. My first attempt with a simplified version was only partial successfull.
The simplifiend json structure looks like this
{
"rowCount": 102,
"data": [
{"id": "56", "bezeichnung": "Main Center", "strasse": "foostreet"},
{"id": "34", "bezeichnung": "Side Location", "strasse": "5th aveneue"}
]
}
For the outer json { "rowCount":102, "data":[]} i have a class jsonEnvelope which looks like this
public class JsonEnvelope
{
public int RowCount { get; set; }
public Location[] Data{ get; set; }
}
To parse the json inside the array data "data":[] i have class location which looks like this
public class Location
{
public string id;
public string bezeichnung;
public string strasse;
}
My code to parse the json looks like this
string jsonString = GetJsonFromFile();
var jsonEnvelope = new JsonEnvelope();
var options = new JsonSerializerOptions();
options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
jsonEnvelope = JsonSerializer.Deserialize<JsonEnvelope>(jsonString, options);
foreach (Location h in jsonEnvelope.Data)
{
Console.WriteLine(String.Format("{0} in {1}", h.bezeichnung, h.strasse));
}
Console.WriteLine("row count = " + jsonEnvelope.RowCount);
What is working?
The line jsonEnvelope.RowCount works. The number 102 is written to the console
The foreach is not working the values of h.bezeichnung and h.strasse are not written to the console
Question
while writing my question i figured it out - i will self answer it briefly
The problem was that i used a field in class location instead of property.
Changing the class location to this solved the issue
public class Location
{
public string Id { get; set; }
public string Bezeichnung { get; set; }
public string Strasse { get; set; }
}
Please note that with:
.NET 5 or
System.Text.Json package version 5 added to Core3.1 projects you can use IncludeFields option:
var serializeOptions = new JsonSerializerOptions
{
IncludeFields = true,
};
var o = JsonSerializer.Deserialize<Location>(json, serializeOptions);

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; }
}

json newtonsoft : Deserialize Object containing a list of string

I have the following issue with this json :
{
"EVTS": {
"EVT": [
{ "ID": "123456",
"KEY1" : "somekey",
"CATEG": [
"cat1",
"cat2",
"cat3"
]
}
]}
}
and this c# class:
public class myClass{
public string ID { get; set; }
public string KEY1 { get; set; }
public list<string> CATEG { get; set; }
}
public class ESObject1
{
[JsonProperty("EVT")]
public List<myClass> EVT { get; set; }
}
public class ESObject0
{
[JsonProperty("EVTS")]
public ESObject1 EVTS { get; set; }
}
}
here i call the deserializer :
ESObject0 globalobject = JsonConvert.DeserializeObject<ESObject0>(json);
But this last code doesnt work, i throws this exception : System.ArgumentException: Could not cast or convert from System.String to System.Collections.Generic.List1[System.String].`
Instead of list<string> i used string [] and only string nothing seems to work.
how can i deserialize this object correctly please.
Thank you.
There doesn't seem to be any apparent problem wit hyour code as this working example illustrates:
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
public class myClass
{
public string ID { get; set; }
public string KEY1 { get; set; }
public List<string> CATEG { get; set; }
}
public class ESObject1
{
[JsonProperty("EVT")]
public List<myClass> EVT { get; set; }
}
public class ESObject0
{
[JsonProperty("EVTS")]
public ESObject1 EVTS { get; set; }
}
class Program
{
static void Main()
{
string json =
#"{
""EVTS"": {
""EVT"": [
{
""ID"": ""123456"",
""KEY1"": ""somekey"",
""CATEG"": [
""cat1"",
""cat2"",
""cat3""
]
}
]
}
}";
ESObject0 globalobject = JsonConvert.DeserializeObject<ESObject0>(json);
foreach (string item in globalobject.EVTS.EVT[0].CATEG)
{
Console.WriteLine(item);
}
}
}
Maybe you just fed a wrong json value to the deserializer which doesn't look like as the one shown in your question. By the way, the one shown i nyour question is invalid JSON as you are missing a , after KEY1 property declaration.
UPDATE:
Now that you have shown your real JSON (coming from http://donnees.ville.quebec.qc.ca/Handler.ashx?id=69&f=JSON) it appears that there's a row where CATEG is not an array of strings but a simple string:
""CATEG"": ""Conférence""
Now that's a pretty bad design because they are mixing arrays and simple properties. I am afraid that in order to deal with this situation you will need to use JObjects and extract the information you need by testing the actual underlying type.
For example:
var obj = JObject.Parse(json);
var events = (JArray)obj["EVTS"]["EVT"];
foreach (JObject evt in events)
{
var categories = evt["CATEG"];
if (categories is JArray)
{
// you've got a list of strings so you can loop through them
string[] cats = ((JArray)categories)
.Select(x => x.Value<string>())
.ToArray();
}
else
{
// you've got a simple string
string cat = categories.Value<string>();
}
}
I have done this many times with many many headaches. My advice is take the json output and use a tool similar to this to write your class for you (http://json2csharp.com/).
Then go over any nullable variables and add nullable type (ex. using int? for int) where needed.

How do I deserialize a custom node in Json to c#, whose name keeps changing?

Below is a section of json I receive from an endpoint.
If you look at the Json below, 'User-Defined-Network-Name' is a custom node and the name will change each time.
How do I define a C# object for this Json?
"addresses": {
"public": [{
"version": 6,
"address": "2005:4600:788e:0910:1a72:81c0:ff03:c7y6"
},
{
"version": 4,
"address": "197.68.xx.xxx"
}],
"private": [{
"version": 4,
"address": "10.xx.xx.xxx"
}],
"User-Defined-Network-Name": [{
"version": 4,
"address": "192.xxx.x.xxx"
}]
}
This is how far I have come -
[Serializable]
public class Addresses
{
public List<Public> #public { get; set; }
public List<Private> #private { get; set; }
}
Im using 'JavascriptSerializer' class to deserialize json.
Thanks,
Ryan
addresses can be deserialized to a type like Dictionary<string,List<YourClass>> where YourClass holds version and addresss.
var obj = new JavaScriptSerializer().Deserialize<Root>(jsonstring);
--
public class Root
{
public Dictionary<string,List<VersionAddress>> addresses;
//Your other fields/properties
}
public class VersionAddress
{
public string version;
public string address;
}
You could take advantage of the dynamic nature of C#:
// this could come from user input:
string userDefinedName = "User-Defined-Network-Name";
    string json = "YOUR JSON COMES HERE";
var serializer = new JavaScriptSerializer();
dynamic result = serializer.DeserializeObject(json);
int version = result["addresses"][userDefinedName][0]["version"];
string address = result["addresses"][userDefinedName][0]["address"];
Console.WriteLine(version);
Console.WriteLine(address);
and if you wanted to loop through the results:
foreach (dynamic item in result["addresses"][userDefinedName])
{
int version = item["version"];
string address = item["address"];
Console.WriteLine(version);
Console.WriteLine(address);
}
Why don't you make network names a dictionary, with key of network name ?
Then you can just iterate over it.
I would not recommend using JavaScriptSerializer, as it has been deprecated. If you want a third-party solution, JSON.Net is pretty good from what I hear.
However, I'm one that's weird about dependencies, so I typically roll my own if it doesn't exist already. Fortunately, this one isn't too hard due to DataContractJsonSerializer from the System.Runtime.Serialization namespace.
All you need to do is first define all the objects in a nested fashion:
using System.Reflection;
using System.Runtime.Serialization; // You will have to add a reference
using System.Runtime.Serialization.Json; // to System.Runtime.Serialization.dll
[DataContract]
public class AddressInfo
{
[DataMember(Name = "address")]
public string Address { get; set; }
[DataMember(Name = "version")]
public int Version { get; set; }
}
[DataContract]
public class AddressList
{
[DataMember(Name = "public")]
public IEnumerable<AddressInfo> Public { get; set; }
[DataMember(Name = "private")]
public IEnumerable<AddressInfo> Private { get; set; }
[DataMember(Name = "User-Defined-Network-Name")]
public IEnumerable<AddressInfo> UserDefined { get; set; }
}
Then a couple helper methods to do the deserialization:
// This will change the DataMember.Name at runtime!
// This will only work if you know the node name in advance.
static void SetUserDefinedNodeName(string userDefinedNodeName)
{
var type = typeof(AddressList);
var property = type.GetProperty("UserDefined", BindingFlags.Default);
var attribute = property.GetCustomAttribute<DataMemberAttribute>();
if (attribute != null)
attribute.Name = userDefinedNodeName;
}
static T Deserialize<T>(string jsonText, string userDefinedNodeName)
{
SetUserDefinedNodeName(userDefinedName);
var jsonBytes = Encoding.UTF8.GetBytes(jsonText);
using (var stream = new MemoryStream(jsonBytes))
{
var serializer = new DataContractJsonSerializer(typeof(T));
var obj = serializer.ReadObject(stream) as T;
return obj;
}
}
Then you use it like so:
var jsonText = // get your json text somehow
var addressList = Deserialize<AddressList>(jsonText);

Categories