Skip to content

Commit

Permalink
Optimize JSON schema.
Browse files Browse the repository at this point in the history
  • Loading branch information
kingcean committed Mar 1, 2024
1 parent c18983b commit e4accb1
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 9 deletions.
21 changes: 18 additions & 3 deletions Core/Data/Result/DataResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime;
using System.Runtime.Serialization;
Expand Down Expand Up @@ -44,18 +45,21 @@ public MessageResult(string message)

/// <summary>
/// Gets or sets the message.
/// It could be an error message, a status description or a notice text. This can be null if no more such information.
/// </summary>
[DataMember(Name = "message", EmitDefaultValue = false)]
[JsonPropertyName("message")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
[Description("The additional message for this operation. It could be an error message, a status description or a notice text. This can be null if no more such information.")]
public string Message { get; set; }

/// <summary>
/// Gets or sets the tracking identifier.
/// Gets or sets the tracking identifier which is used to mark a transaction of operation process..
/// </summary>
[DataMember(Name = "track", EmitDefaultValue = false)]
[JsonPropertyName("track")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
[Description("A tracking ID to mark the transaction of operation process.")]
public string TrackingId { get; set; }
}

Expand Down Expand Up @@ -93,10 +97,11 @@ public DataResult(T data, string message)
}

/// <summary>
/// Gets or sets the data.
/// Gets or sets the data content.
/// </summary>
[DataMember(Name = "data")]
[JsonPropertyName("data")]
[Description("The data content of the result.")]
public T Data { get; set; }

/// <summary>
Expand Down Expand Up @@ -153,6 +158,7 @@ public DataResult(TData data, TInfo additional, string message)
/// </summary>
[DataMember(Name = "info")]
[JsonPropertyName("info")]
[Description("The additional information of the result.")]
public TInfo AdditionalInfo { get; set; }
}

Expand Down Expand Up @@ -195,6 +201,7 @@ public JsonDataResult(JsonObjectNode data, string message)
[DataMember(Name = "data")]
[JsonPropertyName("data")]
[JsonConverter(typeof(JsonObjectNodeConverter))]
[Description("The data content of the result.")]
public JsonObjectNode Data { get; set; }

/// <summary>
Expand All @@ -203,6 +210,7 @@ public JsonDataResult(JsonObjectNode data, string message)
[DataMember(Name = "info")]
[JsonPropertyName("info")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
[Description("The additional information of the result.")]
public JsonObjectNode AdditionalInfo { get; set; }

/// <summary>
Expand Down Expand Up @@ -359,14 +367,16 @@ public CollectionResult(IEnumerable<T> col, int offset, string message, int? cou
[DataMember(Name = "offset", EmitDefaultValue = false)]
[JsonPropertyName("offset")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public int? Offset { get; set; }
[Description("The record offset of the result collection.")]
public int? Offset { get; set; }

/// <summary>
/// Gets or sets the total count.
/// </summary>
[DataMember(Name = "count", EmitDefaultValue = false)]
[JsonPropertyName("count")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
[Description("The count of the result collection.")]
public int? TotalCount { get; set; }

/// <summary>
Expand All @@ -380,6 +390,7 @@ public CollectionResult(IEnumerable<T> col, int offset, string message, int? cou
/// </summary>
[DataMember(Name = "col")]
[JsonPropertyName("col")]
[Description("The data collection of the result.")]
public IEnumerable<T> Value { get; set; }

/// <summary>
Expand All @@ -388,6 +399,7 @@ public CollectionResult(IEnumerable<T> col, int offset, string message, int? cou
[DataMember(Name = "info")]
[JsonPropertyName("info")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
[Description("The addition information of the result.")]
public JsonObjectNode AdditionalInfo { get; set; }

/// <summary>
Expand Down Expand Up @@ -591,6 +603,7 @@ public ErrorMessageResult(string message, string errorCode) : base(message)
[DataMember(Name = TokenInfo.ErrorCodeProperty, EmitDefaultValue = false)]
[JsonPropertyName(TokenInfo.ErrorCodeProperty)]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
[Description("The error code.")]
public string ErrorCode { get; set; }

/// <summary>
Expand All @@ -599,6 +612,7 @@ public ErrorMessageResult(string message, string errorCode) : base(message)
[DataMember(Name = "details", EmitDefaultValue = false)]
[JsonPropertyName("details")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
[Description("The error details.")]
public List<string> Details { get; set; }

/// <summary>
Expand All @@ -607,5 +621,6 @@ public ErrorMessageResult(string message, string errorCode) : base(message)
[DataMember(Name = "info")]
[JsonPropertyName("info")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
[Description("The additional information of the result.")]
public JsonObjectNode AdditionalInfo { get; set; }
}
6 changes: 6 additions & 0 deletions Core/Reflection/Objects/ObjectConvert.cs
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,9 @@ public static bool TryGetProperty<T>(object obj, string propertyName, out T resu
catch (InvalidOperationException)
{
}
catch (NotSupportedException)
{
}
catch (NullReferenceException)
{
}
Expand Down Expand Up @@ -573,6 +576,9 @@ public static bool TryGetProperty<T>(object obj, PropertyInfo prop, out T result
catch (InvalidOperationException)
{
}
catch (NotSupportedException)
{
}
catch (NullReferenceException)
{
}
Expand Down
82 changes: 76 additions & 6 deletions Core/Text/Json/Values.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Cryptography;
using System.Text.Json.Serialization;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

using Trivial.Collection;
using Trivial.Data;
Expand All @@ -20,8 +23,6 @@
using SystemJsonArray = System.Text.Json.Nodes.JsonArray;
using SystemJsonValue = System.Text.Json.Nodes.JsonValue;
using SystemJsonNode = System.Text.Json.Nodes.JsonNode;
using System.Threading.Tasks;
using System.Security;

namespace Trivial.Text;

Expand Down Expand Up @@ -473,7 +474,7 @@ public static string GetPropertyName(PropertyInfo property)
/// <param name="handler">The additional handler to control the creation.</param>
/// <returns>The JSON schema description instance; or null, if not supported.</returns>
public static JsonNodeSchemaDescription CreateSchema(JsonObjectNode json, string desc = null, IJsonNodeSchemaCreationHandler<IJsonDataNode> handler = null)
=> CreateSchema(json, 2, desc, handler);
=> CreateSchema(json, 10, desc, handler);

/// <summary>
/// Creates a JSON schema of a type.
Expand All @@ -483,7 +484,7 @@ public static JsonNodeSchemaDescription CreateSchema(JsonObjectNode json, string
/// <param name="handler">The additional handler to control the creation.</param>
/// <returns>The JSON schema description instance; or null, if not supported.</returns>
public static JsonNodeSchemaDescription CreateSchema<T>(string desc = null, IJsonNodeSchemaCreationHandler<Type> handler = null)
=> CreateSchema(typeof(T), 2, desc, handler);
=> CreateSchema(typeof(T), 10, desc, handler);

/// <summary>
/// Creates a JSON schema of a type.
Expand All @@ -493,7 +494,7 @@ public static JsonNodeSchemaDescription CreateSchema<T>(string desc = null, IJso
/// <param name="handler">The additional handler to control the creation.</param>
/// <returns>The JSON schema description instance; or null, if not supported.</returns>
public static JsonNodeSchemaDescription CreateSchema(Type type, string desc = null, IJsonNodeSchemaCreationHandler<Type> handler = null)
=> CreateSchema(type, 2, desc, handler);
=> CreateSchema(type, 10, desc, handler);

internal static JsonOperationDescription CreateDescriptionByAttribute(MemberInfo member)
{
Expand Down Expand Up @@ -691,7 +692,7 @@ private static JsonNodeSchemaDescription CreateSchema(Type type, int level, stri
try
{
var jsonSerializer = type.GetCustomAttributes<JsonConverterAttribute>()?.FirstOrDefault();
if (jsonSerializer != null) return handler.Convert(type, jsonSchema, breadcrumb);
if (jsonSerializer?.ConverterType != null) return handler.Convert(type, CreateSchema(jsonSerializer, type, jsonSchema) ?? jsonSchema, breadcrumb);
}
catch (NotSupportedException)
{
Expand All @@ -706,6 +707,28 @@ private static JsonNodeSchemaDescription CreateSchema(Type type, int level, stri
var name = GetPropertyName(prop);
if (string.IsNullOrEmpty(name)) continue;
desc = StringExtensions.GetDescription(prop);
try
{
var jsonSerializer = prop.GetCustomAttributes<JsonConverterAttribute>()?.FirstOrDefault();
var converter = GetSchemaCreationHandler(jsonSerializer);
if (converter != null)
{
var propJsonSchema = new JsonObjectSchemaDescription
{
Description = desc
};
var propDesc = converter.Convert(type, propJsonSchema, new(type, null));
if (propDesc != null) jsonSchema.Properties[name] = handler.Convert(type, propDesc, breadcrumb);
continue;
}
}
catch (NotSupportedException)
{
}
catch (TypeLoadException)
{
}

var propSchema = CreateSchema(prop.PropertyType, level, desc, handler, new(prop.PropertyType, breadcrumb, name));
if (propSchema != null) jsonSchema.Properties[name] = propSchema;
}
Expand Down Expand Up @@ -987,4 +1010,51 @@ internal static void RemoveJsonNodeSchemaDescriptionExtendedProperties(JsonObjec
if (onlyBase) return;
json.Remove(new[] { "type", "title", "deprecated", "readOnly", "writeOnly", "allOf", "anyOf", "oneOf", "not", "enum", "definitions" });
}

private static JsonNodeSchemaDescription CreateSchema(JsonConverterAttribute jsonSerializer, Type type, JsonObjectSchemaDescription jsonSchema)
{
var converter = GetSchemaCreationHandler(jsonSerializer);
return converter == null ? jsonSchema : converter.Convert(type, jsonSchema, new(type, null));
}

private static IJsonNodeSchemaCreationHandler<Type> GetSchemaCreationHandler(JsonConverterAttribute jsonSerializer)
{
if (jsonSerializer?.ConverterType == null || !typeof(IJsonNodeSchemaCreationHandler<Type>).IsAssignableFrom(jsonSerializer.ConverterType)) return null;
try
{
return Activator.CreateInstance(jsonSerializer.ConverterType) as IJsonNodeSchemaCreationHandler<Type>;
}
catch (ArgumentException)
{
}
catch (AmbiguousMatchException)
{
}
catch (TargetException)
{
}
catch (TargetInvocationException)
{
}
catch (TargetParameterCountException)
{
}
catch (MemberAccessException)
{
}
catch (InvalidOperationException)
{
}
catch (NotSupportedException)
{
}
catch (NullReferenceException)
{
}
catch (ExternalException)
{
}

return null;
}
}

0 comments on commit e4accb1

Please sign in to comment.