10

I have a generic class, whose children I want to serialize with the value of only one of its attributes.

To this end, I wrote a custom JsonConverter and attached it to the base class with the JsonConverter(Type) Attribute - however, it does not ever seem to be called. For reference, as shown in the example below, I am serializing a List<> of the object using the System.Web.Mvc.Controller.Json() method.

If there is an altogether better way of achieving the same result, I'm absolutely open to suggestions.

Example

View function

public JsonResult SomeView()
{
    List<Foo> foos = GetAListOfFoos();
    return Json(foos);
}

Custom JsonConverter

class FooConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        System.Diagnostics.Debug.WriteLine("This never seems to be run");
        // This probably won't work - I have been unable to test it due to mentioned issues.
        serializer.Serialize(writer, (value as FooBase<dynamic, dynamic>).attribute);
    }

    public override void ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override bool CanConvert(Type objectType)
    {
        System.Diagnostics.Debug.WriteLine("This never seems to be run either");
        return objectType.IsGenericType
            && objectType.GetGenericTypeDefinition() == typeof(FooBase<,>);
    }
}

Foo base class

[JsonConverter(typeof(FooConverter))]
public abstract class FooBase<TBar, TBaz>
    where TBar : class
    where TBaz : class
{
    public TBar attribute;
}

Foo implementation

public class Foo : FooBase<Bar, Baz>
{
    // ...
}

Current output

[
    {"attribute": { ... } },
    {"attribute": { ... } },
    {"attribute": { ... } },
    ...
]

Desired output

[
    { ... },
    { ... },
    { ... },
    ...
]

3 Answers 3

16

What happened to me was, I added the using statement automatically as suggested by Visual Studio. And by mistake added using System.Text.Json.Serialization; instead of using Newtonsoft.Json;

So I was using System.Text.Json.Serialization.JsonConverterAttribute on the target class. Which is (correctly) ignored by Json.Net.

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

3 Comments

This happened to me as well (in the converter class)
Exactly what happened to me too.
This had me and my colleague stumped for the best part of two hours!!
7

First of all System.Web.Mvc.Controller.Json() doesn't work with Json.NET - it uses JavaScriptSerializer that doesn't know anything about your Json.NET stuff. If you still want to use System.Web.Mvc.Controller.Json() call you should do something like this. Also change WriteJson to this:

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
    serializer.Serialize(writer, ((dynamic)value).attribute);
}

I think this should make your code work.

4 Comments

I was under the impression it did, though wouldn't be surprised if I were wrong - perhaps it was something else that pulled Json.NET as a dependency. Thanks for the article, I'll give it a read.
ASP.NET WebApi uses JSON.NET as json serializer, but ASP.NET MVC doesn't. I know it's confusing.
Ah, that would have been it.
Can confirm that this was the underlying issue. Thank you for your assistance.
1

Documentation says: To apply a JsonConverter to the items in a collection use either JsonArrayAttribute, JsonDictionaryAttribute or JsonPropertyAttribute and set the ItemConverterType property to the converter type you want to use.

http://james.newtonking.com/json/help/html/SerializationAttributes.htm

Maybe that will help.

1 Comment

I'll have a look, thanks. Spent ages trawling through the docs, but didn't really know what I was looking for.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.