2

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?

5
  • Look into library Newtonsoft.Json like Newton.Json.JsonConvert.DeserializeObject<YOURCLASS> this should help you out :) Commented Dec 12, 2018 at 5:08
  • newtonsoft.com/json Commented Dec 12, 2018 at 5:09
  • Hi sjdm, please see my requirement I need to serialize into a specific structure, not straightforward class to json serialisation. Commented Dec 12, 2018 at 5:29
  • You can use the JsonConvert.SerializeObject(); method to build your own json string however you like, have a look through the documentation to do this. The newtonsoft library goes both ways. Commented Dec 12, 2018 at 5:36
  • Quick question: did you accept dbc answer after already accepting a different answer first? Thanks, I test something for a secret hat. Commented Dec 12, 2018 at 13:58

4 Answers 4

2

As you have tagged your question with , 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:

Sample fiddle here.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for the perfect solution. this is what i was expecting.
If we have many varieties of intended attributes (like amount, code, value in the below example) then can we have a generic class to the server different types? { "risk": { "code": "reg" }, "rent": { "amount": 50000 }, "city": { "value": "A001" } }
@BadriPrasad - not information in your comment for me to say. You might want to ask a second question with your complete requirements.
1

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..

1 Comment

This also works for my requirement, but I have many attributes where I will receive as indeded value attributes. Instead of creating classes I would prefer to have an attribute level decoration method to solve the requirement. Anyhow thanks for the suggestions.
0

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>();

2 Comments

It is not satisfy what OP's want.
please see my requirement I need to serialize into a specific structure, not a straightforward class to json serialisation.
0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.