Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for DriveInfo, FileInfo, and DirectoryInfo #150

Merged
merged 3 commits into from
Jan 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions src/Argon/Converters/DirectoryInfoConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
class DirectoryInfoConverter :
JsonConverter<DirectoryInfo>
{
public override void WriteJson(JsonWriter writer, DirectoryInfo? value, JsonSerializer serializer)
{
if (value != null)
{
writer.WriteValue(value.ToString().Replace('\\', '/'));
}
}

public override DirectoryInfo? ReadJson(JsonReader reader, Type type, DirectoryInfo? existingValue, bool hasExisting, JsonSerializer serializer)
{
if (reader.Value is string value)
{
return new(value.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar));
}

return null;
}
}
21 changes: 21 additions & 0 deletions src/Argon/Converters/DriveInfoConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
class DriveInfoConverter :
JsonConverter<DriveInfo>
{
public override void WriteJson(JsonWriter writer, DriveInfo? value, JsonSerializer serializer)
{
if (value != null)
{
writer.WriteValue(value.Name.Replace('\\', '/'));
}
}

public override DriveInfo? ReadJson(JsonReader reader, Type type, DriveInfo? existingValue, bool hasExisting, JsonSerializer serializer)
{
if (reader.Value is string value)
{
return new(value);
}

return null;
}
}
21 changes: 21 additions & 0 deletions src/Argon/Converters/FileInfoConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
class FileInfoConverter :
JsonConverter<FileInfo>
{
public override void WriteJson(JsonWriter writer, FileInfo? value, JsonSerializer serializer)
{
if (value != null)
{
writer.WriteValue(value.ToString().Replace('\\', '/'));
}
}

public override FileInfo? ReadJson(JsonReader reader, Type type, FileInfo? existingValue, bool hasExisting, JsonSerializer serializer)
{
if (reader.Value is string value)
{
return new(value.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar));
}

return null;
}
}
22 changes: 3 additions & 19 deletions src/Argon/Serialization/DefaultContractResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,14 @@ public class DefaultContractResolver : IContractResolver
// Json.NET Schema requires a property
internal static IContractResolver Instance { get; } = new DefaultContractResolver();


static readonly string[] blacklistedTypeNames =
{
"System.IO.DriveInfo",
"System.IO.FileInfo",
"System.IO.DirectoryInfo"
};

static readonly JsonConverter[] builtInConverters =
{
new ExpandoObjectConverter(),
new DiscriminatedUnionConverter(),
new KeyValuePairConverter(),
new DriveInfoConverter(),
new DirectoryInfoConverter(),
new FileInfoConverter(),
new RegexConverter()
};

Expand Down Expand Up @@ -237,20 +232,9 @@ protected virtual JsonObjectContract CreateObjectContract(Type type)
SetExtensionDataDelegates(contract, extensionDataMember);
}

// serializing DirectoryInfo without ISerializable will stackoverflow
// https://github.com/JamesNK/Newtonsoft.Json/issues/1541
if (Array.IndexOf(blacklistedTypeNames, type.FullName) != -1)
{
contract.OnSerializingCallbacks.Add(ThrowUnableToSerializeError);
}

return contract;
}

[DoesNotReturn]
static void ThrowUnableToSerializeError(object o, StreamingContext context) =>
throw new JsonSerializationException($"Unable to serialize instance of '{o.GetType()}'.");

static MemberInfo? GetExtensionDataMemberForType(Type type)
{
var members = GetClassHierarchyForType(type).SelectMany(baseType =>
Expand Down
74 changes: 74 additions & 0 deletions src/Tests/Converters/IoInfos.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Copyright (c) 2007 James Newton-King. All rights reserved.
// Use of this source code is governed by The MIT License,
// as found in the license.md file.

#nullable enable
public class IoInfos : TestFixtureBase
{

static DriveInfo driveInfo = DriveInfo.GetDrives()[0];
static FileInfo fileInfo = new($"one{Path.DirectorySeparatorChar}two.txt");
static DirectoryInfo directoryInfo = new(Path.Combine($"one{Path.DirectorySeparatorChar}two"));

[Fact]
public void Test_DirectoryInfo()
{
var serialized = JsonConvert.SerializeObject(directoryInfo);
Assert.Equal("\"one/two\"", serialized);
var result = JsonConvert.DeserializeObject<DirectoryInfo>(serialized);
Assert.Equal(directoryInfo.FullName, result.FullName);
}

[Fact]
public void Test_FileInfo()
{
var serialized = JsonConvert.SerializeObject(fileInfo);
Assert.Equal("\"one/two.txt\"", serialized);
var result = JsonConvert.DeserializeObject<FileInfo>(serialized);
Assert.Equal(fileInfo.FullName, result.FullName);
}

[Fact]
public void Test_DriveInfo()
{
var serialized = JsonConvert.SerializeObject(driveInfo);
Assert.Equal($"\"{driveInfo.Name.Replace('\\', '/')}\"", serialized);
var result = JsonConvert.DeserializeObject<DriveInfo>(serialized);
Assert.Equal(driveInfo.Name, result.Name);
}

[Fact]
public void Nested()
{
var target = new Target
{
DirectoryInfo = directoryInfo,
DriveInfo = driveInfo,
FileInfo = fileInfo
};
var result = JsonConvert.SerializeObject(target);
Assert.Equal($$"""{"DirectoryInfo":"one/two","FileInfo":"one/two.txt","DriveInfo":"{{driveInfo.Name.Replace('\\', '/')}}"}""", result);
var deserialize = JsonConvert.DeserializeObject<Target>(result);

Assert.Equal(target.DirectoryInfo.FullName, deserialize.DirectoryInfo!.FullName);
Assert.Equal(target.DirectoryInfo.ToString(), deserialize.DirectoryInfo!.ToString());
Assert.Equal(target.DriveInfo.Name, deserialize.DriveInfo!.Name);
Assert.Equal(target.FileInfo.FullName, deserialize.FileInfo!.FullName);
Assert.Equal(target.FileInfo.ToString(), deserialize.FileInfo!.ToString());
}

[Fact]
public void NestedNull()
{
var result = JsonConvert.SerializeObject(new Target());
Assert.Equal("""{"DirectoryInfo":null,"FileInfo":null,"DriveInfo":null}""", result);
JsonConvert.DeserializeObject<Target>(result);
}

public class Target
{
public DirectoryInfo? DirectoryInfo { get; set; }
public FileInfo? FileInfo { get; set; }
public DriveInfo? DriveInfo { get; set; }
}
}
39 changes: 0 additions & 39 deletions src/Tests/Issues/Issue1541.cs

This file was deleted.