Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

JsonConvert SerializeObject not including class property names for a [Serializable] class

Ask Question

I'm serializing a List of objects of a MediaInfo class I have created. When this comes out, I end up with:

Object:
    ClassName: "WVO.Media",
    Data: Array():
        1: null
        5: "A3000"
        8: "Oakland
        ... etc...

In short, I'm getting the class property as an integer keyed array instead of with property names. Serialization code is pretty straight forward. First I load the list (List mediaInfos) and then call:

JsonConvert.SerializeObject(mediaInfos);

I can Response.Write things like:

Response.Write(mediaInfos[0].MediaTown);

... and get the correct output, but I'm confused as to why the property names aren't included in the JSon output. What am I missing?

EDIT:

using System;
using System.Data;
using System.Runtime.Serialization;
using System.Collections.Generic;
using CMS;
using CMS.DataEngine;
using CMS.Helpers;
using WVO;
[assembly: RegisterObjectType(typeof(MediaInfo), MediaInfo.OBJECT_TYPE)]
namespace WVO
    [Serializable]
    public class MediaInfo : AbstractInfo<MediaInfo>
        #region "Type information"
        public const string OBJECT_TYPE = "wvo.media";
        public static ObjectTypeInfo TYPEINFO = new    ObjectTypeInfo(typeof(MediaInfoProvider), OBJECT_TYPE, "WVO.Media", "MediaID", null, null, null, null, null, null, null, null)
            ModuleName = "wvo",
            TouchCacheDependencies = true,
            DependsOn = new List<ObjectDependency>() 
                new ObjectDependency("MediaMarketID", "wvo.mediamarket",  ObjectDependencyEnum.NotRequired), 
                new ObjectDependency("MediaStateID", "cms.state", ObjectDependencyEnum.NotRequired), 
                new ObjectDependency("MediaTypeID", "wvo.mediatype", ObjectDependencyEnum.NotRequired), 
                new ObjectDependency("MediaSizeID", "wvo.mediasize", ObjectDependencyEnum.NotRequired), 
        #endregion
        #region "Properties"
        [DatabaseField]
        public virtual int MediaID
                return ValidationHelper.GetInteger(GetValue("MediaID"), 0);
                SetValue("MediaID", value);
        [DatabaseField]
        public virtual string MediaPanel
                return ValidationHelper.GetString(GetValue("MediaPanel"),    String.Empty);
                SetValue("MediaPanel", value, String.Empty);
        [DatabaseField]
        public virtual string MediaTown
                return ValidationHelper.GetString(GetValue("MediaTown"),   String.Empty);
                SetValue("MediaTown", value, String.Empty);
        ... [several other properties similarly formatted] ...
        #endregion
        #region "Type based properties and methods"
        protected override void DeleteObject()
            MediaInfoProvider.DeleteMediaInfo(this);
        protected override void SetObject()
            MediaInfoProvider.SetMediaInfo(this);
        #endregion
        #region "Constructors"
        public MediaInfo(SerializationInfo info, StreamingContext context)
            : base(info, context, TYPEINFO)
        public MediaInfo()
            : base(TYPEINFO)
        public MediaInfo(DataRow dr)
            : base(TYPEINFO, dr)
        #endregion

Thanks!

You don't show the base class AbstractInfo<MediaInfo>, but I notice that you have marked your class as [Serializable]. This allows me to make a guess as to what your problem is.

What the Serializable attribute means is, "The following .Net type can be serialized by serializing its public and private fields -- not its properties." By default Json.NET ignores this attribute, however it is possible to force it to serialize types with this attribute in this manner by setting IgnoreSerializableAttribute on DefaultContractResolver to false. And in fact, asp.net does just this, globally enabling this behavior. Thus if your AbstractInfo<T> base class actually stores its data in some private indexed array, Json.NET will output that private array instead of the public properties.

Now let's try to reproduce the problem with a minimal example. Consider the following classes:

[Serializable]
public abstract class AbstractInfo<T>
    object[] Data;
    protected AbstractInfo(int tableSize)
        Data = new object[tableSize];
    protected object GetValue(int index)
        return Data[index];
    protected void SetValue(int index, object value)
        Data[index] = value;
[Serializable]
public class MediaInfo : AbstractInfo<MediaInfo>
    public MediaInfo() : base(1) { }
    public virtual string MediaPanel
            return (string)GetValue(0) ?? string.Empty;
            SetValue(0, value == "" ? null : value);

If I serialize this to JSON, the Data array appears rather than the property:

        var test = new MediaInfo { MediaPanel = "panel" };
        var settings = new JsonSerializerSettings { ContractResolver = new DefaultContractResolver { IgnoreSerializableAttribute = false } };
        var json = JsonConvert.SerializeObject(test, settings);
        Console.WriteLine(json); 
        // Prints {"Data":["panel"]}

Thus it appears this is almost certainly your problem.

To work around the problem, you can

  • Set IgnoreSerializableAttribute = true globally in asp.net. To do this see ASP.NET Web API and [Serializable] class or Setting IgnoreSerializableAttribute Globally in Json.net.

  • Mark your class with [JsonObject(MemberSerialization = MemberSerialization.OptOut)]:

    [Serializable]
    [JsonObject(MemberSerialization = MemberSerialization.OptOut)]
    public class MediaInfo : AbstractInfo<MediaInfo>
            

    Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question. Provide details and share your research!

    But avoid

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers.

  •