使用StringEnumConverter生成模式

时间:2014-09-08 08:05:02

标签: json.net schema

是否可以使用Json.NET生成一个模式,将枚举值输出为字符串而不是整数?我注意到有人分叉代码来执行此操作,但是想知道是否有其他方法可以执行此操作,或者是否有任何计划要执行此操作。

修改

要明确的是,我尝试使用它来生成架构:

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

return schema.ToString();

3 个答案:

答案 0 :(得分:7)

通过NuGet包管理器安装Newtonsoft.Json.Schema包,然后您可以将枚举输出为开箱即用的字符串。

给定课程

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

public enum Options 
{
    Option1,
    Option2
}

将按如下方式生成模式,无需使用[JsonConverter(typeof(StringEnumConverter))]属性修饰类/属性。

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

image

答案 1 :(得分:1)

我遇到了同样的问题。我写了一个hack,通过反射用枚举替换整数。还在等待官方修复。

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

未对所有测试用例进行测试。

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 + @"}");
        }
    }

}

答案 2 :(得分:0)

使用以下代码将枚举作为字符串序列化架构,并确保还调整了值类型。

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());