Why are DriveInfo's properties missing when serializing to json string using Json.NET?

試著忘記壹切 提交于 2019-12-12 00:40:13

问题


Attempting to serialize DrivInfo to a Json string with this code only return the "name" property:

DriveInfo dr = new DriveInfo("C");    
string json = Newtonsoft.Json.JsonConvert.SerializeObject(dr);

The string result is only: {"_name":"C:\"}

DrivInfo is sealed so I cannot change anything. Is there a way to do it excluding wrapping?


回答1:


The class contains its own custom serialization which specifies that only the _name field should be included. The other properties aren't stored in the class. They're determined by the environment, so they can't be replaced with deserialized values.

From the source code:

private const String NameField = "_name";  // For serialization

    void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
    {
        // No need for an additional security check - everything is public.
        info.AddValue(NameField, _name, typeof(String));
    }

Other properties are determined by actually inspecting the drive referenced by the DriveInfo. Properties like TotalFreeSpace and TotalFreeSize can change from moment to moment and may not (probably don't) apply on another computer where the class could be deserialized.

If you could serialize the whole thing and deserialize it someplace else, then it would be possible to create a deserialized instance of the class where all of the property values are wrong, because, for example, they actually describe the c: drive on another computer. But the purpose of the class is to return information about a drive on the computer where the code is executing.

If you want to pass that data around then you can always create your own class and serialize that.




回答2:


Your difficulty is that DriveInfo implements the ISerializable interface for custom serialization, and Json.NET respects this interface by default, using it to serialize and deserialize the type. And since DriveInfo is defined entirely by the name of the drive, that's all that it's custom serialization code stores into the serialization stream.

Since you just want to dump the properties of DriveInfo and do not care about deserialization, you can disable use of ISerializable by setting DefaultContractResolver.IgnoreSerializableInterface = true. However, if you do this, you'll get an infinite recursion serializing dr.RootDirectory.Root.Root.... To work around this, you could create a JsonConverter for DirectoryInfo:

public class DirectoryInfoConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(DirectoryInfo);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null)
            return null;
        var token = JToken.Load(reader);
        return new DirectoryInfo((string)token);
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        writer.WriteValue(value.ToString());
    }
}

Then you could do:

DriveInfo dr = new DriveInfo("C");
var settings = new JsonSerializerSettings 
{ 
    ContractResolver = new DefaultContractResolver { IgnoreSerializableInterface = true },
    Converters = new [] { new DirectoryInfoConverter() },
};
var json = Newtonsoft.Json.JsonConvert.SerializeObject(dr, Formatting.Indented, settings);

But at this point, it's probably easier just to serialize an intermediate anonymous type:

var json = JsonConvert.SerializeObject(
    new
    {
        Name = dr.Name,
        DriveType = dr.DriveType,
        DriveFormat = dr.DriveFormat,
        IsReady = dr.IsReady,
        AvailableFreeSpace = dr.AvailableFreeSpace,
        TotalFreeSpace = dr.TotalFreeSpace,
        TotalSize = dr.TotalSize,
        RootDirectory = dr.RootDirectory.ToString(),
        VolumeLabel = dr.VolumeLabel
    },
    Formatting.Indented);

(Of course, you won't be able to deserialize it in this format.)



来源:https://stackoverflow.com/questions/37170011/why-are-driveinfos-properties-missing-when-serializing-to-json-string-using-jso

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!