【问题标题】:Use JSON.NET to generate JSON schema with extra attributes使用 JSON.NET 生成带有额外属性的 JSON 模式
【发布时间】:2012-05-03 20:25:41
【问题描述】:

我正在使用 JSON.NET 从 c# 对象类生成 JSON Schema。但我无法添加任何其他 json 模式属性,例如maxLength、模式(验证电子邮件的正则表达式)等

以下是我的工作代码,我只能生成具有必需属性的 json 模式。如果有人可以发布一些关于如何为 json 模式添加这些额外属性的代码示例,那就太好了。

谢谢,

我的代码示例

public class Customer
{
    [JsonProperty(Required = Required.Always)]
    public int CustomerID { get; set; }

    [JsonProperty(Required = Required.Always)]
    public string FirstName { get; set; }

    [JsonProperty(Required = Required.Always)]
    public string LastName { get; set; }

    [JsonProperty(Required = Required.Always)]
    public string Email { get; set; }

    [JsonProperty(Required = Required.AllowNull)]
    public string Phone { get; set; }
}

{
    "title" : "Customer",
    "type" : "object",
    "properties" : {
        "CustomerID" : {
            "required" : true,
            "type" : "integer"
        },
        "FirstName" : {
            "required" : true,
            "type" : "string"
        },
        "LastName" : {
            "required" : true,
            "type" : "string"
        },
        "Email" : {
            "required" : true,
            "type" : "string"
        },
        "Phone" : {
            "required" : true,
            "type" : [
                "string",
                "null"
            ]
        }
    }
}

【问题讨论】:

    标签: c# json.net jsonschema


    【解决方案1】:

    您可以使用 JavaScriptSerializer 类。如:

    namespace ExtensionMethods
    {
        public static class JSONHelper
        {
            public static string ToJSON(this object obj)
            {
                JavaScriptSerializer serializer = new JavaScriptSerializer();
                return serializer.Serialize(obj);
            }
    
            public static string ToJSON(this object obj, int recursionDepth)
            {
                JavaScriptSerializer serializer = new JavaScriptSerializer();
                serializer.RecursionLimit = recursionDepth;
                return serializer.Serialize(obj);
            }
        }
    }
    

    像这样使用它:

    using ExtensionMethods;
    
    ...
    
    List<Person> people = new List<Person>{
                       new Person{ID = 1, FirstName = "Scott", LastName = "Gurthie"},
                       new Person{ID = 2, FirstName = "Bill", LastName = "Gates"}
                       };
    
    
    string jsonString = people.ToJSON();
    

    另请阅读这篇文章:

    1. http://msdn.microsoft.com/en-us/library/system.web.script.serialization.javascriptserializer.aspx
    2. http://weblogs.asp.net/scottgu/archive/2007/10/01/tip-trick-building-a-tojson-extension-method-using-net-3-5.aspx
    3. http://www.asp.net/AJAX/Documentation/Live/mref/T_System_Web_Script_Serialization_JavaScriptSerializer.aspx

    你也可以试试ServiceStackJsonSerializer

    一个使用它的例子:

     var customer = new Customer { Name="Joe Bloggs", Age=31 };
        var json = JsonSerializer.SerializeToString(customer);
        var fromJson = JsonSerializer.DeserializeFromString<Customer>(json); 
    

    【讨论】:

    • 我不太明白这是如何解决这个问题的。
    【解决方案2】:

    您可以像这样创建自定义 JsonConverter。我使用反射来填写属性。

      public class UserConverter : JsonConverter
    {
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            var user = (User)value;
            var result = new StringBuilder("{");
    
            result.Append("title : " + user.GetType().Name + ", ");
            result.Append("properties : {");
    
            foreach (var prop in user.GetType().GetProperties())
            {
                result.Append(prop.Name + ": {");
                result.Append("value : " + Convert.ToString(prop.GetValue(user, null)) + ", ");
    
                var attribute = (JsonPropertyAttribute)Attribute.GetCustomAttributes(prop)[0];
                if (attribute.Required == Required.Always)
                    result.Append("required : true, ");
    
                result.Append("type : " + prop.PropertyType.Name.ToLower());
                result.Append(" }");
            }
            writer.WriteValue(result.ToString());
        }
    
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            var user = new User { UserName = (string)reader.Value };
    
            return user;
        }
    
        public override bool CanConvert(Type objectType)
        {
            return objectType == typeof(User);
        }
    
    }
    

    [JsonConverter(typeof(UserConverter))]
    public class User
    {
        [JsonProperty(Required = Required.Always)]
        public string UserName { get; set; }
    }
    
    //Run  
    string json = JsonConvert.SerializeObject(manager, Formatting.Indented);
    
    Console.WriteLine(json);
    

    【讨论】:

    • 这很有用,但我认为我不会将 JsonConverter 属性添加到类中,因为当需要使用实际数据(而不是模式)序列化类时,它不会工作。相反,在创建模式时将转换器的实例传递给 SerializeObject 方法。
    【解决方案3】:
    • 首先将你的json文件转换成xml
    • 现在添加要添加的 xml 节点并将 xml 转换为 json。

    这种转换可以通过“newtonsoft.json.jsonconvert”类轻松完成。要使用此类,只需在您的项目中导入 newtonsoft.json dll。

    【讨论】:

    • 这是个坏主意。根本不需要使用 XML 来创建 JSON 模式。此外,在从 JSON 到 XML 来回转换时,结构信息有时会丢失,具体取决于具体情况。
    【解决方案4】:

    Json.NET Schema 现在已大大改进了架构生成支持。

    您可以使用 .NET 的 Data Annotation 属性对属性进行注释,以指定架构上的最小值、最大值、minLength、maxLength 等信息。

    还有 JSchemaGenerationProvider 可让您在为类型生成架构时完全控制。

    更多详情:http://www.newtonsoft.com/jsonschema/help/html/GeneratingSchemas.htm

    【讨论】:

    【解决方案5】:

    James Newton-King 就在 his answer 中,我将用一个代码示例对其进行扩展,这样偶然发现此页面的人就不需要研究整个 documentation

    因此,您可以使用 .NET 提供的属性来指定这些附加选项,例如字符串的最大长度或允许的正则表达式模式。以下是一些示例:

    public class MyDataModel
    {
        public enum SampleEnum { EnumPosition1, EnumPosition2, EnumPosition3 }
    
        [JsonProperty(Required = Required.Always)]
        [RegularExpression(@"^[0-9]+$")]
        public string PatternTest { get; set; }
    
        [JsonProperty(Required = Required.Always)]
        [MaxLength(3)]
        public string MaxLength3 { get; set; }
    
        [JsonProperty(Required = Required.AllowNull)]
        [EnumDataType(typeof(SampleEnum))]
        public string EnumProperty { get; set; }
    }
    

    上面的注解来自System.ComponentModel.DataAnnotations命名空间。

    要使这些附加属性影响生成的 json 架构,您需要使用与 Json.NET 架构 包一起分发的 JSchemaGenerator 类。如果您使用较旧的JsonSchemaGenerator,则需要进行一些升级,因为它现在已被弃用,并且不包含上述新功能。

    这是为上述类生成 Json Schema 的示例函数:

        /// <summary>
        /// Generates JSON schema for a given C# class using Newtonsoft.Json.Schema library.
        /// </summary>
        /// <param name="myType">class type</param>
        /// <returns>a string containing JSON schema for a given class type</returns>
        internal static string GenerateSchemaForClass(Type myType)
        {
            JSchemaGenerator jsonSchemaGenerator = new JSchemaGenerator();
            JSchema schema = jsonSchemaGenerator.Generate(myType);
            schema.Title = myType.Name;
    
            return schema.ToString();
        }
    

    你可以像这样使用它:

     string schema = GenerateSchemaForClass(typeof(MyDataModel));
    

    【讨论】:

    • 自定义属性呢?有什么方法可以例如获取属性上的客户属性值并将它们添加到该属性的架构中?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多