2

I have the following class structure. What I am trying to achieve is instead of Bar serialized as an object in JSON, serialize as string with its inner property Name value and ignore the Id property. And I don't have a scenario where I need to deserialize it, but I have to load the Bar objects from database with other properties and do some internal manipulation but not use it for transport.

class Foo
{
    [JsonProperty("bar")]
    public Bar Bar { get; set; }
}

class Bar
{
    [JsonIgnore]
    public Guid Id { get; set; }
    [JsonProperty]
    public string Name { get; set; }
}

Expected JSON:

{
    bar: "test"
}
0

1 Answer 1

5

Use a custom JsonConverter and you can control your conversion to output whatever you want.

Something like:

    public class BarConverter : JsonConverter
    {

        public override bool CanConvert(Type objectType)
        {
            return objectType == typeof(Bar);
        }

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            var bar = value as Bar;
            serializer.Serialize(writer, bar.Name);
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
              // Note: if you need to read to, you'll need to implement that here too
              // otherwise just throw a NotImplementException and override `CanRead` to return false
              throw new NotImplementedException();
        }
    }

Then you can either decorate your property or the Bar class (depending on whether you always want Bar serialized like this, or only for this property) with the JsonConverterAttribute:

[JsonConverter(typeof(BarConverter))]
public Bar Bar { get; set; }

Or:

[JsonConverter(typeof(BarConverter))]
public class Bar

Another "quick and dirty" way to do it is to just have a shadow property that will be serialized:

public class Foo
{
    [JsonProperty("bar")]         // this will be serialized as "bar"
    public string BarName 
    {
        get { return Bar.Name; }
    }

    [JsonIgnore]                  // this won't be serialized
    public Bar Bar { get; set; }
}

Note if you want to be able to read then you'd need to provide a setter too and figure out how to convert the string name back to an instance of Bar. That's where the quick and dirty solution gets a little unpleasant because you don't have a easy way to restrict setting BarName to just during deserialization.

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

1 Comment

JsonConverter way works out of the box and without introducing any additional property! Thanks

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.