-
Notifications
You must be signed in to change notification settings - Fork 868
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add System.Text.Json serialization/deserialization supports (#1…
…0217) * chore: refactoring JsonUtility code to support newtonsoftjson/systemtextjson switching based on type * chore: add json/yaml serialization test infrastructure * chore: switch XRefMap serialization logics to use System.Text.Json * chore: add json roundtrip test with JsonUtility * chore: Add MarkdigExtensionSetting json roundtrip tests * chore: add ManagedReference YAML roundtrip tests * chore: add UniversalReference YAML roundtrip tests * chore: add ApiPage YAML roundtrip tests * chore: add FilterConfig YAML roundtrip tests * chore: Add Manifest model json roundtrip tests * chore: change JavascriptEncoder settings and add related tests * chore: add TOC model YAML roundtrip tests * chore: add `dummy property name` for deserialize `metadata` key data * chore: add FileMapping/FileItems converters and JSON roundtrip tests * chore: disable `MarkdigExtensionSettingConverter` JSON formatting * chore: add ListWithStringFallback converters and JSON roundtrip test * chore: add FileMetadataPairs converters and JSON roundtrip test * chore: add MergeJsonConfig converters and JSON roundtrip test * chore: add BuildJsonConfig JSON roundtrip test * chore: add MetadataJsonConfig JSON roundtrip test * chore: add DocfxConfig JSON roundtrip test * chore: Switch to use SystemTextJson by default and fix related tests * chore: modify converter to throw JsonException if unexpected token found * chore: merge changes of FileMetadataPairsConverter.cs
- Loading branch information
Showing
127 changed files
with
14,628 additions
and
405 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
63 changes: 63 additions & 0 deletions
63
src/Docfx.App/Config/FileMetadataPairsConverter.NewtonsoftJson.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using Docfx.Common; | ||
|
||
using Newtonsoft.Json; | ||
using Newtonsoft.Json.Linq; | ||
|
||
namespace Docfx; | ||
|
||
internal partial class FileMetadataPairsConverter | ||
{ | ||
/// <summary> | ||
/// JsonConverter for FileMetadataPairs | ||
/// </summary> | ||
internal class NewtonsoftJsonConverter : JsonConverter | ||
{ | ||
/// <inheritdoc/> | ||
public override bool CanConvert(Type objectType) | ||
{ | ||
return objectType == typeof(FileMetadataPairs); | ||
} | ||
|
||
/// <inheritdoc/> | ||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) | ||
{ | ||
IEnumerable<JToken> jItems; | ||
if (reader.TokenType == JsonToken.StartObject) | ||
{ | ||
jItems = JContainer.Load(reader); | ||
} | ||
else throw new JsonReaderException($"{reader.TokenType} is not a valid {objectType.Name}."); | ||
return new FileMetadataPairs(jItems.Select(ParseItem).ToList()); | ||
} | ||
|
||
/// <inheritdoc/> | ||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) | ||
{ | ||
writer.WriteStartObject(); | ||
foreach (var item in ((FileMetadataPairs)value).Items) | ||
{ | ||
writer.WritePropertyName(item.Glob.Raw); | ||
writer.WriteRawValue(JsonUtility.Serialize(item.Value)); | ||
} | ||
writer.WriteEndObject(); | ||
} | ||
|
||
private static FileMetadataPairsItem ParseItem(JToken item) | ||
{ | ||
if (item.Type == JTokenType.Property) | ||
{ | ||
JProperty jProperty = item as JProperty; | ||
var pattern = jProperty.Name; | ||
var rawValue = jProperty.Value; | ||
return new FileMetadataPairsItem(pattern, rawValue); | ||
} | ||
else | ||
{ | ||
throw new JsonReaderException($"Unsupported value {item} (type: {item.Type})."); | ||
} | ||
} | ||
} | ||
} |
78 changes: 78 additions & 0 deletions
78
src/Docfx.App/Config/FileMetadataPairsConverter.SystemTextJson.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System.Linq; | ||
using System.Text.Json; | ||
using System.Text.Json.Serialization; | ||
using Docfx.Common; | ||
|
||
#nullable enable | ||
|
||
namespace Docfx; | ||
|
||
internal partial class FileMetadataPairsConverter | ||
{ | ||
/// <summary> | ||
/// JsonConverter for FileMetadataPairs | ||
/// </summary> | ||
internal class SystemTextJsonConverter : JsonConverter<FileMetadataPairs> | ||
{ | ||
public override FileMetadataPairs Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) | ||
{ | ||
if (reader.TokenType != JsonTokenType.StartObject) | ||
{ | ||
throw new JsonException($"{reader.TokenType} is not a valid {typeToConvert.Name}."); | ||
} | ||
|
||
using var document = JsonDocument.ParseValue(ref reader); | ||
var properties = document.RootElement.EnumerateObject(); | ||
var items = properties.Select(x => new FileMetadataPairsItem(x.Name, ToInferredType(x.Value))).ToArray(); | ||
return new FileMetadataPairs(items); | ||
} | ||
|
||
public override void Write(Utf8JsonWriter writer, FileMetadataPairs value, JsonSerializerOptions options) | ||
{ | ||
writer.WriteStartObject(); | ||
foreach (var item in value.Items) | ||
{ | ||
writer.WritePropertyName(item.Glob.Raw); | ||
writer.WriteRawValue(JsonUtility.Serialize(item.Value)); | ||
} | ||
writer.WriteEndObject(); | ||
} | ||
|
||
/// <summary> | ||
/// Convert JsonElement to .NET object. | ||
/// </summary> | ||
private static object? ToInferredType(JsonElement elem) | ||
{ | ||
switch (elem.ValueKind) | ||
{ | ||
case JsonValueKind.Null: | ||
return null; | ||
case JsonValueKind.True: | ||
return true; | ||
case JsonValueKind.False: | ||
return false; | ||
case JsonValueKind.String when elem.TryGetDateTime(out DateTime datetime): | ||
return datetime; | ||
case JsonValueKind.String: | ||
return elem.GetString(); | ||
case JsonValueKind.Array: | ||
return elem.EnumerateArray().Select(ToInferredType).ToArray(); | ||
case JsonValueKind.Object: | ||
var properties = elem.EnumerateObject(); | ||
return properties.ToDictionary(x => x.Name, x => ToInferredType(x.Value)); | ||
case JsonValueKind.Number when elem.TryGetInt32(out int intValue): | ||
return intValue; | ||
case JsonValueKind.Number when elem.TryGetInt64(out long longValue): | ||
return longValue; | ||
case JsonValueKind.Number: | ||
return elem.GetDouble(); | ||
case JsonValueKind.Undefined: | ||
default: | ||
throw new JsonException($"JsonValueKind({elem.ValueKind}) is not supported."); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
72 changes: 72 additions & 0 deletions
72
src/Docfx.App/Config/ListWithStringFallbackConverter.NewtonsoftJson.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using Newtonsoft.Json; | ||
using Newtonsoft.Json.Linq; | ||
|
||
namespace Docfx; | ||
|
||
|
||
internal partial class ListWithStringFallbackConverter | ||
{ | ||
/// <summary> | ||
/// JsonConverter for <see cref="ListWithStringFallback"/>. | ||
/// </summary> | ||
internal class NewtonsoftJsonConverter : JsonConverter | ||
{ | ||
/// <inheritdoc/> | ||
public override bool CanConvert(Type objectType) | ||
{ | ||
return objectType == typeof(FileMapping); | ||
} | ||
|
||
/// <inheritdoc/> | ||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) | ||
{ | ||
var model = new ListWithStringFallback(); | ||
var value = reader.Value; | ||
IEnumerable<JToken> jItems; | ||
if (reader.TokenType == JsonToken.StartArray) | ||
{ | ||
jItems = JArray.Load(reader); | ||
} | ||
else if (reader.TokenType == JsonToken.StartObject) | ||
{ | ||
jItems = JContainer.Load(reader); | ||
} | ||
else if (reader.TokenType == JsonToken.String) | ||
{ | ||
jItems = JRaw.Load(reader); | ||
} | ||
else | ||
{ | ||
jItems = JObject.Load(reader); | ||
} | ||
|
||
if (jItems is JValue) | ||
{ | ||
model.Add(jItems.ToString()); | ||
} | ||
else | ||
{ | ||
foreach (var item in jItems) | ||
{ | ||
model.Add(item.ToString()); | ||
} | ||
} | ||
|
||
return model; | ||
} | ||
|
||
/// <inheritdoc/> | ||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) | ||
{ | ||
writer.WriteStartArray(); | ||
foreach (var item in (ListWithStringFallback)value) | ||
{ | ||
serializer.Serialize(writer, item); | ||
} | ||
writer.WriteEndArray(); | ||
} | ||
} | ||
} |
56 changes: 56 additions & 0 deletions
56
src/Docfx.App/Config/ListWithStringFallbackConverter.SystemTextJson.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System.IO; | ||
using System.Text.Json; | ||
using System.Text.Json.Serialization; | ||
using YamlDotNet.Serialization; | ||
|
||
namespace Docfx; | ||
|
||
|
||
internal partial class ListWithStringFallbackConverter | ||
{ | ||
/// <summary> | ||
/// JsonConverter for <see cref="ListWithStringFallback"/>. | ||
/// </summary> | ||
internal class SystemTextJsonConverter : JsonConverter<ListWithStringFallback> | ||
{ | ||
public override ListWithStringFallback Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) | ||
{ | ||
var tokenType = reader.TokenType; | ||
switch (tokenType) | ||
{ | ||
case JsonTokenType.String: | ||
{ | ||
var value = reader.GetString(); | ||
return new ListWithStringFallback([value]); | ||
} | ||
case JsonTokenType.StartArray: | ||
{ | ||
var items = JsonSerializer.Deserialize<string[]>(ref reader, options); | ||
return new ListWithStringFallback(items); | ||
} | ||
case JsonTokenType.StartObject: | ||
{ | ||
using var document = JsonDocument.ParseValue(ref reader); | ||
JsonElement root = document.RootElement; | ||
var values = root.EnumerateObject().Select(x=>x.ToString()); | ||
return new ListWithStringFallback(values); | ||
} | ||
default: | ||
throw new JsonException($"TokenType({reader.TokenType}) is not supported."); | ||
} | ||
} | ||
|
||
public override void Write(Utf8JsonWriter writer, ListWithStringFallback value, JsonSerializerOptions options) | ||
{ | ||
writer.WriteStartArray(); | ||
foreach (var item in value) | ||
{ | ||
writer.WriteStringValue(item); | ||
} | ||
writer.WriteEndArray(); | ||
} | ||
} | ||
} |
Oops, something went wrong.