是否可以使用Json.NET生成一个模式,将枚举值输出为字符串而不是整数?我注意到有人分叉代码来执行此操作,但是想知道是否有其他方法可以执行此操作,或者是否有任何计划要执行此操作。
修改
要明确的是,我尝试使用它来生成架构:
var schemaGenerator = new JsonSchemaGenerator();
var schema = schemaGenerator.Generate(typeof(Class1));
return schema.ToString();
答案 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);
答案 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());