Reputation: 117
we have our C# class as below
public class PrimaryContact
{
public string PrefixTitle { get; set; }
public string SurName { get; set; }
public string GivenName { get; set; }
}
we need to serialise to the json object as
"primaryContact": {
"prefixTitle": {
"value": "mrs"
},
"surName": "abcd",
"givenName": "abcd"
}
Please note the prefixTitle is intended with value. for some selected attributes we need to serialize like this. Also, we need to read from JSON and deserialise into the class. Is there any generic best approach we can follow by decorating the elements so that we can achieve this result?
Upvotes: 2
Views: 2428
Reputation: 3070
You need to write a custom serializer for your object. Here is an example to show how you can do this with extending JsonConverter and using some custom attribute to determine if your object/property should wrapped:
[WrapperAttribute(Key = "primaryContact")]
public class PrimaryContact
{
[WrapperAttribute(Key= "prefixTitle")]
public string PrefixTitle { get; set; }
public string SurName { get; set; }
public string GivenName { get; set; }
}
public class WrapperAttribute : Attribute
{
public string Key { get; set; }
}
public class WrapperSerializer : JsonConverter<PrimaryContact>
{
public override void WriteJson(JsonWriter writer, PrimaryContact value, JsonSerializer serializer)
{
Type type = value.GetType();
JObject root = new JObject();
foreach (var property in type.GetAllProperties())
{
if (property.HasAttribute<WrapperAttribute>())
{
JProperty wrappedProperty = new JProperty(property.GetAttribute<WrapperAttribute>().Key);
JObject wrappedChild = new JObject();
wrappedProperty.Value = wrappedChild;
JProperty wrappedChildProperty = new JProperty("value");
wrappedChildProperty.Value = JToken.FromObject(property.GetValue(value));
wrappedChild.Add(wrappedChildProperty);
root.Add(wrappedProperty);
}
else
{
var childProperty = new JProperty(property.Name);
childProperty.Value = JToken.FromObject(property.GetValue(value));
root.Add(childProperty);
}
}
if (type.HasAttribute<WrapperAttribute>())
{
JObject wrappedRoot = new JObject();
var wrappedProperty = new JProperty(type.GetAttribute<WrapperAttribute>().Key);
wrappedProperty.Value = root;
wrappedRoot.Add(wrappedProperty);
wrappedRoot.WriteTo(writer);
}
else
{
root.WriteTo(writer);
}
}
public override PrimaryContact ReadJson(JsonReader reader, Type objectType, PrimaryContact existingValue, bool hasExistingValue,
JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
in main :
PrimaryContact contact = new PrimaryContact();
contact.GivenName = "test name";
contact.PrefixTitle = "test title";
contact.SurName = "test surname";
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.Converters.Add(new WrapperSerializer());
var serialized = JsonConvert.SerializeObject(contact, settings);
output :
{
"primaryContact": {
"prefixTitle": {
"value": "test title"
},
"SurName": "test surname",
"GivenName": "test name"
}
}
Upvotes: 0
Reputation: 32
Here Prefix Title Also a class not a string. Here your class want to look like this.
public class PrimaryContact
{
public PrefixTitle prefixTitle{ get; set; }
public string surName{ get; set; }
public string givenName{ get; set; }
}
public class PrefixTitle {
public string value {get; set;}
}
Install Newtonsoft.json libraby file to your project : -> Open Package manager console in Tools NuGet Package and paste it then hit enter.
Install-Package Newtonsoft.Json -Version 12.0.1
Convert a Class to Json :
string output = JsonConvert.SerializeObject(classname);
Convert a Json to Object :
Here object denotes a Class
Object output = JsonConvert.DeSerializeObject<object>(jsonString);
Here You can find optimized code you can use in your project directly :
public static string getJsonFromClass(object objectName){
return JsonConvert.SerializeObject(object);
}
public static T getObjectFromJson<T>(string jsonString){
T t = default(T);
try{
t = JsonConvert.DeSerializeObject<T>(classname);
}catch(Exception e){
Debug.WriteLine(e.Message);
}
return t;
}
You can use this Method to achieve your output by :
string jsonData = getJsonFromClass(Prefix);
string JsonString = "<here your json string>";
Prefix getObjectFromJson = getObjectFromJson<Prefix>(JsonString);
thats all ..
I hope this can help for you..
Upvotes: 1
Reputation: 116741
As you have tagged your question with json.net, you can do this by applying a custom JsonConverter
to the "selected attributes" that should be nested inside a {"value" : ... }
object when serialized.
First, define the following converter:
public class NestedValueConverter<T> : JsonConverter
{
class Value
{
public T value { get; set; }
}
public override bool CanConvert(Type objectType)
{
throw new NotImplementedException();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
switch (reader.MoveToContent().TokenType)
{
case JsonToken.Null:
return null;
default:
return serializer.Deserialize<Value>(reader).value;
}
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
serializer.Serialize(writer, new Value { value = (T)value });
}
}
public static partial class JsonExtensions
{
public static JsonReader MoveToContent(this JsonReader reader)
{
if (reader.TokenType == JsonToken.None)
reader.Read();
while (reader.TokenType == JsonToken.Comment && reader.Read())
;
return reader;
}
}
Now, apply it the "selected attributes" of PrimaryContact
as follows:
public class PrimaryContact
{
[JsonConverter(typeof(NestedValueConverter<string>))]
public string PrefixTitle { get; set; }
public string SurName { get; set; }
public string GivenName { get; set; }
}
And you will be able to deserialize and serialize as follows:
var settings = new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
};
var root = JsonConvert.DeserializeObject<RootObject>(jsonString, settings);
var json2 = JsonConvert.SerializeObject(root, Formatting.Indented, settings);
Notes:
As the converter is intended to be applied directly using the attributes [JsonConverter(typeof(NestedValueConverter<...>))]
or [JsonProperty(ItemConverterType = typeof(NestedValueConverter<...>))]
, CanConvert
, which is only called when the converter is included in settings, is not implemented.
The converter is generic in case you need to nest non-string values.
Sample fiddle here.
Upvotes: 2
Reputation: 818
You can achieve this by changing your model like:
public class PrimaryContact
{
public Prefix PrefixTitle { get; set; }
public string SurName { get; set; }
public string GivenName { get; set; }
}
public class Prefix
{
public string Value { get; set; }
}
Then
Newton.Json.JsonConvert.DeserializeObject<PrimaryContact>();
Upvotes: 0