Creating a schema using StringEnumConverter

Is it possible to create a schema with Json.NET that outputs enum values ​​as strings rather than integers? I noticed that someone was unwrapping the code to do this, but was wondering if there was another way to do this, or if there were any plans to do this.

EDIT

To be clear, I'm trying to use this to create a schematic:

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

return schema.ToString();

      

+3


source to share


3 answers


Install the package Newtonsoft.Json.Schema

through the NuGet Package Manager, then you can output enums as strings out of the box.

Lesson data

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

public enum Options 
{
    Option1,
    Option2
}

      

The schema will be generated as follows, no need to decorate the classes / properties [JsonConverter(typeof(StringEnumConverter))]

.



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

      


image

+6


source


I had the same problem. I wrote a hack that replaces integers with enums through reflection. Still awaiting an official fix.

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

      



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

}

      

+1


source


Use the following code to serialize an enumerated string schema and make sure the value type is also configured.

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

      

0


source







All Articles