how to get json property name - c#

I have a class like following:
public class Client {
[JsonProperty("first_name")]
public string FirstName { get; set; }
[JsonProperty("last_name")]
public string LastName { get; set; }
}
using the following code I can get the properties and values in a dictionary of that class object:
var propertyValuesByName = client.GetType().GetProperties()
.Where(pi => pi.PropertyType == typeof(string))
.Select(pi => new { Val = (string) pi.GetValue(client), Name = pi.Name })
.ToDictionary(pi => pi.Name, pi => pi.Val);
so the dictionary contains property name as key and the property value as value. But what I want is, get the dictionary which key will be the object JsonProperty name instead of the real property name, means instead of "FirstName" I want "first_name" as key. How can I modify the above code to achieve this?

To get the property name of a JSON object in C#, you can use the nameof operator. For example, given the following JSON object:
{
"name": "John Smith",
"age": 30,
"city": "New York"
}
You can use the nameof operator to get the property names like this:
string name = nameof(jsonObject.name); // "name"
string age = nameof(jsonObject.age); // "age"
string city = nameof(jsonObject.city); // "city"
Note that the nameof operator only works with compile-time constants, so it will not work with dynamically generated property names.
Alternatively, you can use the JsonPropertyAttribute to specify the property name in the JSON object. For example:
public class Person
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("age")]
public int Age { get; set; }
[JsonProperty("city")]
public string City { get; set; }
}
you can then use reflection to get the property names like this:
var person = new Person { Name = "John Smith", Age = 30, City = "New York" };
foreach (var property in person.GetType().GetProperties())
{
var jsonPropertyAttribute = property.GetCustomAttribute<JsonPropertyAttribute>();
if (jsonPropertyAttribute != null)
{
string propertyName = jsonPropertyAttribute.PropertyName;
}
}

Use some more reflection to ger info from custom attribute:
.Select(pi => new
{
Val = (string) pi.GetValue(client),
Name = pi.GetCustomAttribute<JsonPropertyAttribute>()?.PropertyName ?? pi.Name
})
Or :
.Select(pi => new
{
Val = (string) pi.GetValue(client),
Name = (pi.GetCustomAttribute(typeof(JsonPropertyAttribute)) as JsonPropertyAttribute)?.PropertyName ?? pi.Name
})
Also note that if your object contains only string you can deserialize directly to Dictionary<string, string>.

I guess it's similar to the problem exposed in this thread :
How to get Json Property name using reflection in C#
If it's not mandatory for you to access object using reflection, you can just deserialize a Json to a Dictionary<string,string> like this :
var values = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
and then get the keys out of it using values.Keys.
Hope this helps

Related

Convert json string from one type to another with .net core c#

I am struggling to convert below input json to output json as this is what is the required format to call
hubspot api to submit a form. I am writing this using .net core within Azure function.
Input Json
{
"Email":"myemail#test.com",
"Phone":"12345678",
"Address":"address 1"
}
Output json
{
"fields": [
{
"name": "Email",
"value": "myemail#test.com"
},
{
"name": "Phone",
"value": "12345678"
},
{
"name": "Address",
"value": "address 1"
}
]
}
I converted the input json to dictionary using
IDictionary<string, string> dictionary = JsonConvert.DeserializeObject<IDictionary<string, string>>(inputJson);
but that gives me key value pair instead of name value pair.
I would like the output as detailed above.
Any help/example code would be highly appreciated.
You could create your own "NameValuePair" class/struct if you don't want "Key" as the field name:
public class FieldContainer
{
[JsonProperty("fields")]
public IEnumerable<NameValuePair> Fields { get; set; }
}
public struct NameValuePair
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("value")]
public string Value { get; set; }
public NameValuePair(string name, string value)
{
Name = name;
Value = value;
}
}
And then do like you've already done, but converting the KeyValuePairs into your own struct:
var inJson = #"{
""Email"":""myemail#test.com"",
""Phone"":""12345678"",
""Address"":""address 1""
}";
var dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(inJson);
var container = new FieldContainer
{
Fields = dict.Select(pair => new NameValuePair(pair.Key, pair.Value))
};
var outJson = JsonConvert.SerializeObject(container);
See this fiddle for a demonstration.
Easiest way to do this would be to take the json and convert it to Dictionary<string, string>. Loop over each KeyValuePair and create a list of Fields using LINQ. Once you have the List of fields, create your RootObject.
public class RootObject
{
[JsonProperty("fields")]
public List<Field> Fields { get; set; }
}
public class Field
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("value")]
public string Value { get; set; }
}
// Create a dictionary
var dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(jsonStr);
// Create a list of Fields
List<Field> fields = dict.Select(x => new Field() { Name = x.Key, Value = x.Value }).ToList();
// Create the final Object.
RootObject rootObj = JsonConvert.SerializeObject(new RootObject() { Fields = fields });
Alternative solution, using JObject.Parse() to parse the original JSON, then iterate its Properties to create an array of JObjects with different names and values.
The resulting IEnumerable<JObject> is then converted to a JArray, used to create the final fields object.
var jObj = JObject.Parse(json);
var newObjects = jObj.Properties().Select(p => new JObject {
new JProperty("name", p.Name),
new JProperty("value", p.Value)});
var fields = new JObject() {
{ "fields", JArray.FromObject(newObjects)}
};
Console.WriteLine(fields);

JSON: Getting properties value in a list on a specific condition using c#

I have a Jobject.
{
"address": "test",
"state": "",
"postcode": "",
"membergroup": {
"User1": false,
"User2": false,
"User3": false,
"User4": true,
"User5": false,
"User6": true
}
}
I am trying to get the membergroup property value for all true values in a list of string using c#.
like {"user4","user6"}
Is this possible?
any suggestion of this please?
You can also use JObect if you don't want to have to create C# objects.
Note:
Serializing this back to a json string in the first step is probably not needed depending on how you are getting your json. It should already be coming in as a json string.
using Newtonsoft.Json.Linq;
var json = JsonConvert.SerializeObject(yourObject);
var entireJson = JToken.Parse(json);
var propertyList = (JObject)entireJson["membergroup"];
foreach (var property in propertyList)
{
var key = property.Key;
var value = (bool)property.Value;
if (value)
{
key.Dump();
}
}
//User4
//User6
Using Json.NET :
Create a class that will represent your json in C#:
public class Entity
{
[JsonProperty("address")]
public string Address { get; set; }
[JsonProperty("state")]
public string State { get; set; }
[JsonProperty("postcode")]
public string PostCode { get; set; }
[JsonProperty("membergroup")]
public Dictionary<string, bool> MemberGroup { get; set; }
}
Get your json in a string, convert it to your c# class and pick only true values for your membergroup.
var entity = JsonConvert.DeserializeObject<Entity>(jsonString);
entity.MemberGroup = entity.MemberGroup.Where(x => x.Value).ToDictionary(k => k.Key, v => v.Value);

Linq select a single field using a string containing the name of the field

Let's say I have a simple list of objects like this:
public class DataField
{
public int DataFieldId {get; set;}
public int KeyId {get; set;}
public string FieldName {get; set;}
public string Data {get; set;}
}
Now I would like to get a list of the values in a Property using the string value of the Property name, like this:
public List<string> getFieldData(List<DataField> dataToSearch, string propertyName)
{
// This is the area I'd like to figure out.
return dataToSearch.Select(ds => ds.propertyName).Distinct.ToList();
}
public void MyMethod()
{
var data = new List<DataField>{
new DataField{DataFieldId = 1, KeyId = 1,
FieldName = "UserName", Data = "jSmith"},
new DataField{DataFieldId = 2, KeyId = 1,
FieldName = "Email", Data = "jSmith#nowhere.com"},
new DataField{DataFieldId = 3, KeyId = 1,
FieldName = "PreferredContact", Data = "Phone"},
new DataField{DataFieldId = 4, KeyId = 2,
FieldName = "UserName", Data = "jDoe"},
new DataField{DataFieldId = 5,KeyId = 2,
FieldName = "Email", Data = "janeDoe#emailServer.net"},
new DataField{DataFieldId = 6, KeyId = 2,
FieldName = "PreferredContact", Data = "Email"}
};
// Notice I want to search using a string
var fieldNames = getFieldData(data, "FieldName");
}
I would want fieldNames to be a List<string> containing:
"UserName"
"Email"
"PreferredContact"
I would like to use a string to specify the column to return.
You can use reflection. You're using "field" but the class actually contains properties, so use reflection's GetProperty() method. If you use fields instead, use GetField()
public static List<string> getFieldData(List<DataField> dataToSearch, string fieldName)
{
// You can use reflection to get information from types at runtime.
// The property_info variable will hold various data about the field
// name you pass in (type, name, etc)
var property_info = typeof(DataField).GetProperty(fieldName);
// We can then call property_info's GetValue() on an instantiated
// object of our class, and it will return the value of that property on that object
return dataToSearch.Select(ds => Convert.ToString(property_info.GetValue(ds))).Distinct().ToList();
}
PropertyInfo class: https://msdn.microsoft.com/en-us/library/system.reflection.propertyinfo(v=vs.110).aspx
Type class: https://msdn.microsoft.com/en-us/library/system.type(v=vs.110).aspx

How to copy all fields from one object to another, but only when destination value is NULL

I'd like to merge one object into another in a generic way that can be used repeatedly for other more complex objects. I only want the NULLs to change.
ie. merge sourcePerson and detinationPerson to get resultingPerson (below)
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int? Age { get; set; }
public string Address { get; set; }
}
var sourcePerson = new Person
{
FirstName = "Bill",
LastName = "Smith",
Age = 43,
Address = "123 Some Street"
};
var destinationPerson = new Person
{
FirstName = "Barbara",
LastName = null,
Age = 41,
Address = null
};
var resultingPerson = new Person
{
FirstName = "Barbara",
LastName = "Smith",
Age = 41,
Address = "123 Some Street"
};
I've tried Automapper, but can't seem to configure it properly. I feel like the following should work. Help?
Mapper.CreateMap<Person, Person>().ForAllMembers(opt => opt.UseDestinationValue());
Mapper.Map(sourcePerson, destinationPerson);
Thanks IronGeek and tutok.
Yes, the following works:
Mapper.CreateMap<Person, Person>()
.ForAllMembers(opt => opt.Condition(person => person.DestinationValue == null));
Your can use reflection like this:
public static T Merge<T>(T source, T destination)
{
var returnvalue = (T) Activator.CreateInstance(typeof (T));
foreach (var field in destination.GetType().GetProperties())
{
field.SetValue(returnvalue,
field.GetValue(destination, null) == null ? field.GetValue(source) : field.GetValue(destination));
}
return returnvalue;
}
I haven't tested this for other than simple DTOs.

Newtonsoft Json Serializer/Deserializer - how to use generic objects instead of JObject?

I have JSON specified by a restful service I am consuming that looks like this as an example:
{
"id": "97",
"name": "Tom Production",
"description": null,
"parameters": [
{
"first_parameter_name": "First Parameter Value"
},
{
"second_parameter_name": "Second Parameter Value"
}
]
}
Note that the property names id, name, description, and parameters are all established as part of the specification. The collection of generic parameters, shown in my example as "first_parameter_name" and "second_parameter_name" are not specified.... could be anything and I want to map them to generically typed objects.
I have declared an object for this as:
[DataContract (Name = "MyClass")]
public class MyClass
{
[DataMember (Name = "id")]
public string Id { get; set; }
[DataMember(Name = "name")]
public string Name { get; set; }
[DataMember(Name = "description")]
public string Description { get; set; }
[DataMember(Name = "parameters")]
public List<object> Parameters { get; set; }
}
Serialization works fine, exactly as I expect:
var myObject = new MyClass();
myObject.Id = "97";
myObject.Name = "Tom Production";
myObject.Parameters = new List<object>();
myObject.Parameters.Add(new { first_parameter_name = "First Parameter Value" });
myObject.Parameters.Add(new { second_parameter_name = "Second Parameter Value" });
string json = JsonConvert.SerializeObject(myObject);
Console.WriteLine(json);
yields the JSON I am looking for, exactly as at the top of this posting.
HOWEVER.
Deserialization does NOT work fine. If it worked the way I hope it to, which would be to create generic types just like I had created, and the following code should work.... but instead it throws a reflection exception:
var myNewObject = JsonConvert.DeserializeObject<MyClass>(json);
foreach (object o in myNewObject.Parameters)
{
Type t = o.GetType();
Console.WriteLine("\tType is {0}", t);
foreach (PropertyInfo pi in t.GetProperties(BindingFlags.Instance | BindingFlags.Public))
{
Console.WriteLine("\t\tName is {0}", pi.Name);
Console.WriteLine("\t\tValue is {0}", pi.GetValue(o, null));
}
}
Instead, I have to write code that is Newtonsoft-specific (ick) to use a kind of fake Newtonsoft reflection:
var myNewObject = JsonConvert.DeserializeObject<MyClass>(json);
foreach (object o in myNewObject.Parameters)
{
var jo = o as JObject;
if (jo != null)
{
foreach (JProperty prop in jo.Properties())
{
Console.WriteLine("\t\tName is {0}", prop.Name);
Console.WriteLine("\t\tValue is {0}", prop.Value);
}
}
}
Is there a way that I can control the Deserializer so that it will generate the proper generic types rather than the JObject type with the JProperties?
Many thanks in advance.
JObjects map most directly to Dictionary<string, object>s, since they're each simply a collection of keys to values. If you know that the value is always a string, you can make it a Dictionary<string, string>.
[DataMember(Name = "parameters")]
public List<Dictionary<string, object>> Parameters { get; set; }
// or
[DataMember(Name = "parameters")]
public List<Dictionary<string, string>> Parameters { get; set; }
// e.g.
var myNewObject = JsonConvert.DeserializeObject<MyClass>(json);
foreach (var dict in myNewObject.Parameters)
{
foreach (var pair in dict)
{
Console.WriteLine("\t\tKey is {0}", pair.Key);
Console.WriteLine("\t\tValue is {0}", pair.Value);
}
}

Categories

Resources