Generate schema using StringEnumConverter

旧城冷巷雨未停 提交于 2019-12-17 21:05:53

问题


Is it possible to generate a schema with Json.NET that outputs enum values as strings rather than integers? I noticed someone had forked the code to do this, but was wondering if there's any other way to do this, or if there are any plans to do it.

EDIT

To be clear, I'm trying to use this to generate a schema:

var schemaGenerator = new JsonSchemaGenerator();
var schema = schemaGenerator.Generate(typeof(Class1));

return schema.ToString();

回答1:


Install Newtonsoft.Json.Schema package via NuGet package manager, then you can output enums as strings out-of-the-box.

Given classes

public class Foo
{
    public Options Bar { get; set; }
}

public enum Options 
{
    Option1,
    Option2
}

Schema would be generated as follows, no need to decorate classes/properties with [JsonConverter(typeof(StringEnumConverter))] attribute.

JSchemaGenerator generator = new JSchemaGenerator();
generator.GenerationProviders.Add(new StringEnumGenerationProvider());
JSchema schema = generator.Generate(typeof(Foo), false);
//Console.WriteLine(schema);




回答2:


I had the same problem. I wrote a hack which replaces integers with enums via reflection. Still waiting for official fix.

var jsonSchemaString =  JsonUtility.getRawJSONSchema(typeof(Class1).FullName);

Not tested with all test cases.

public class JsonUtility
{
    public static string getRawJSONSchema(string jsonObjectTypeName)
    {
        var jsonSchemaGenerator = new JsonSchemaGenerator();

        var myType = Type.GetType(jsonObjectTypeName);

        var schema = jsonSchemaGenerator.Generate(myType);

        schema.Title = myType.Name;

        var enumToFix = new Dictionary<string, string>();

        FindEnums(schema, myType, ref enumToFix);

        var writer = new StringWriter();

        var jsonTextWriter = new JsonTextWriter(writer);

        schema.WriteTo(jsonTextWriter);

        var result = writer.ToString();

        ReplaceEnums(ref result, enumToFix);

        return result;
    }



    //This is a known issue with JsonSchemaGenarator
    //Stay tuned with future releases of JSON.Net package
    //Enums are generator as integers
    //Lets convert intergers to string here
    private static void FindEnums(JsonSchema schema, Type Type, ref Dictionary<string, string> result)
    {

        if (schema.Properties != null)
            foreach (var prop in schema.Properties)
            {
                if (prop.Value.Enum != null)
                {

                    var properties = Type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
                    foreach (var p in properties)
                    {
                        SearchProperty(p, prop.Key, ref result);
                    }


                }
                FindEnums(prop.Value, Type, ref result);
            }

    }



    private static void SearchProperty(PropertyInfo property, string propertyName, ref Dictionary<string, string> result)
    {
        //IF property name is same as JSON property name
        if (property.Name.Trim().ToLower() == propertyName.Trim().ToLower())
        {
            result.Add(property.Name, EnumToJsonArray(property.PropertyType));
            return;
        }
        //Custom JSON property names set via attributes
        foreach (CustomAttributeData customAttr in property.CustomAttributes)
        {
            if (customAttr.AttributeType.Name == "JsonPropertyAttribute")
            {
                foreach (CustomAttributeNamedArgument arg in customAttr.NamedArguments)
                {
                    if (arg.TypedValue.Value.ToString().Trim().ToLower() == propertyName.Trim().ToLower())
                    {
                        result.Add(propertyName, EnumToJsonArray(property.PropertyType));
                        return;
                    }
                }
                foreach (CustomAttributeTypedArgument arg in customAttr.ConstructorArguments)
                {
                    if (arg.Value.ToString().Trim().ToLower() == propertyName.Trim().ToLower())
                    {
                        result.Add(propertyName, EnumToJsonArray(property.PropertyType));
                        return;
                    }
                }
            }
        }



        PropertyInfo[] info = property.PropertyType.GetProperties(BindingFlags.Public | BindingFlags.Instance);

        if (info.Length > 0)
        {
            foreach (var item in info)
            {
                SearchProperty(item, propertyName, ref result);
            }
        }

    }

    private static string EnumToJsonArray(Type type)
    {
        if (!type.IsEnum)
            throw new InvalidOperationException("enum expected");

        var results =
            Enum.GetValues(type).Cast<object>().Select(enumValue => enumValue.ToString())
                .ToList();

        return Newtonsoft.Json.JsonConvert.SerializeObject(results);

    }

    private static void ReplaceEnums(ref string result, Dictionary<string, string> enumToFix)
    {
        foreach (var item in enumToFix)
        {
            result = Regex.Replace(result, @"""" + item.Key + ".*?}", @"""" + item.Key + @""":{""required"":true,""type"":""string"",""enum"":" + item.Value + @"}");
        }
    }

}



回答3:


Use the following code to serialize schema with enums as strings and make sure that value type is also adjusted.

JsonConvert.DefaultSettings = () => new JsonSerializerSettings()
{
    Converters = new List<JsonConverter>()
    {
        new StringEnumConverter()
    }
};
var gen = new JSchemaGenerator()
{
    DefaultRequired = Required.Default,
    ContractResolver = new CamelCasePropertyNamesContractResolver()
};
var myType = typeof(ConfigRoot);
var schema = gen.Generate(myType);

var schemaObj = JObject.Parse(schema.ToString());
var enumNodes = schemaObj.SelectTokens("$..enum");
foreach (var node in enumNodes)
{
    var enumTypeNode = node.Parent.Parent;
    enumTypeNode["type"] = "string";    
}

Console.WriteLine(schemaObj.ToString());


来源:https://stackoverflow.com/questions/25719779/generate-schema-using-stringenumconverter

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