将JSON中带const的anyOf枚举结构序列化到C#的最优方案
问题背景
我正在编写C#程序,需要导入符合某JSON Schema的数据。该Schema的作者将部分枚举类型设计为由带const字符串属性的对象组成的anyOf数组,示例如下:
ApplicationType Schema片段
"ApplicationType": { "$id": "#ApplicationType", "anyOf": [ { "additionalProperties": false, "properties": { "description": { "const": "Consent to make small (minor material) changes to a project with Planning Permission", "type": "string" }, "value": { "const": "amendment.minorMaterial", "type": "string" } }, "required": [ "value", "description" ], "type": "object" }, { "additionalProperties": false, "properties": { "description": { "const": "Consent to make small (non-material) changes to a project with Planning Permission", "type": "string" }, "value": { "const": "amendment.nonMaterial", "type": "string" } }, "required": [ "value", "description" ], "type": "object" } ] }
FileType Schema片段
"FileType": { "$id": "#FileType", "anyOf": [ { "additionalProperties": false, "properties": { "description": { "const": "Elevations - existing", "type": "string" }, "value": { "const": "elevations.existing", "type": "string" } }, "required": [ "value", "description" ], "type": "object" }, { "additionalProperties": false, "properties": { "description": { "const": "Elevations - proposed", "type": "string" }, "value": { "const": "elevations.proposed", "type": "string" } }, "required": [ "value", "description" ], "type": "object" } ] }
使用NJsonSchema导入这些结构时,生成的是带可写字符串属性的对象,没有保留原Schema中的const值。我希望能在代码中保留这些const值,用于数据验证和导入,目前尝试了三种方案但都不尽人意:
方案一:导入为枚举
将上述结构转换为带自定义特性的枚举类型:
enum EApplicationType { [Code("amendment.minorMaterial")] ConsentToMakeSmallMinorMaterialChangesToAProjectWithPlanningPermission, [Code("amendment.nonMaterial")] ConsentToMakeSmallNonMaterialChangesToAProjectWithPlanningPermission, } enum EFileType { [Code("elevations.existing")] ElevationsExisting, [Code("elevations.proposed")] ElevationsProposed, }
优势:每个枚举有独立的类型约束;
不足:枚举与字符串值的转换、枚举项遍历都需要大量反射操作,虽可通过预加载字典规避,但增加了实现复杂度。
方案二:使用静态类+字符串属性
将const值封装为静态类的只读字符串属性:
static class ApplicationType { public static string ConsentToMakeSmallMinorMaterialChangesToAProjectWithPlanningPermission => "amendment.minorMaterial"; public static string ConsentToMakeSmallNonMaterialChangesToAProjectWithPlanningPermission => "amendment.nonMaterial"; } static class FileType { public static string ElevationsExisting => "elevations.existing"; public static string ElevationsProposed => "elevations.proposed"; }
优势:实现简单,可直接通过字符串比较进行验证;
不足:没有类型约束(任意字符串都可传入),遍历所有可选值仍需反射。
方案三:使用类/实例对象
沿用原Schema的对象结构,定义对应类型或静态实例:
方式A:实现接口的类
public class ConsentToDisplayAnAdvertisement : IApplicationType { public string Description => "ConsentToDisplayAnAdvertisement"; public string Value => "advertConsent"; public int CompareTo(object obj) { return Value.CompareTo((obj as IApplicationType).Value); } }
方式B:静态类持有实例
public static class EEApplicationType { public static DescriptionValue ConsentToMakeSmallChangesToAProjectWithPlanningPermission = new DescriptionValue ( "ConsentToMakeSmallChangesToAProjectWithPlanningPermission", "amendment" ); }
优势:完全匹配原Schema的结构;
不足:对象实例无法直接用于switch语句,遍历所有可选值仍依赖反射。
请问是否有更优的实现方式?
内容的提问来源于stack exchange,提问作者Jamie Kitson
相关产品推荐
相关产品推荐

