2017-12-20 13 views
2

나는 다음과 같은 유형이 주어 :Newtonsoft.Json.Schema를 사용하면 "정의"이름의 생성을 가로채는 방법이 있습니까?

public class MyClass 
{ 
    public MyGenericClass<bool> Gen { get; set; } 
} 

public class MyGenericClass<T> 
{ 
    [Required] 
    public T Prop { get; set; } 
} 

을하고 난 것을 제외하고 대단한 다음 스키마

{ 
    "definitions": { 
    "MyGenericClass<Boolean>": { 
     "type": [ 
     "object", 
     "null" 
     ], 
     "properties": { 
     "prop": { 
      "type": "boolean" 
     } 
     }, 
     "required": [ 
     "prop" 
     ] 
    } 
    }, 
    "type": "object", 
    "properties": { 
    "gen": { 
     "$ref": "#/definitions/MyGenericClass<Boolean>" 
    } 
    }, 
    "required": [ 
    "gen" 
    ] 
} 

을 얻을 수 있도록

var generator = new JSchemaGenerator 
{ 
    ContractResolver = new CamelCasePropertyNamesContractResolver(), 
    SchemaIdGenerationHandling = SchemaIdGenerationHandling.None 
}; 

generator.GenerationProviders.Add(
    new StringEnumGenerationProvider { CamelCaseText = true }); 

같은 스키마 생성기를 설정 스키마 '<>'이 싫어서 스키마를 공유해야하는 서비스.

<>을 제거 할 수 있도록 정의 이름 생성을 차단하는 방법이 있습니까? 다른 SchemaIdGenerationHandling 중 하나도 작동하지 않습니다.

public class GenericSchemaProvider : JSchemaGenerationProvider 
{ 
    public override bool CanGenerateSchema(JSchemaTypeGenerationContext context) 
    { 

     return context.ObjectType.IsGenericType && !context.ObjectType.IsAssignableFrom(typeof(IEnumerable)); 
    } 

    public override JSchema GetSchema(JSchemaTypeGenerationContext context) 
    { 
     return CanGenerateSchema(context) ? CreateSchemaWithCustomId(context, context.Required) : null; 
    } 

    private static JSchema CreateSchemaWithCustomId(JSchemaTypeGenerationContext context, Required required) 
    { 
     var schema = context.Generator.Generate(context.ObjectType, required != Required.Always); 
     schema.Id = new Uri(TypeName(context.ObjectType), UriKind.Relative); 
     return schema; 
    } 

    private static string TypeName(Type type, string acc = "") 
    { 
     var name = type.Name; 
     var index = name.IndexOf('`'); 
     return index == -1 ? acc+name : TypeName(type.GetGenericArguments()[0],acc+name.Substring(0, index)); 
    } 
} 

같은

성가 시게 일이 거의

{ 
    "definitions": { 
    "MyGenericClassNullableDouble": { 
     "$id": "MyGenericClassNullableDouble", 
     "type": [ 
     "object", 
     "null" 
     ], 
     "properties": { 
     "prop": { 
      "type": "number" 
     } 
     }, 
     "required": [ 
     "prop" 
     ] 
    }, 
    "MyGenericClassDouble": { 
     "$id": "MyGenericClassDouble", 
     "type": [ 
     "object", 
     "null" 
     ], 
     "properties": { 
     "prop": { 
      "type": "number" 
     } 
     }, 
     "required": [ 
     "prop" 
     ] 
    }, 
    "MyGenericClassBoolean": { 
     "$id": "MyGenericClassBoolean", 
     "type": [ 
     "object", 
     "null" 
     ], 
     "properties": { 
     "prop": { 
      "type": "boolean" 
     } 
     }, 
     "required": [ 
     "prop" 
     ] 
    } 
    }, 
    "type": "object", 
    "properties": { 
    "genBool": { 
     "$ref": "MyGenericClassBoolean" 
    }, 
    "genDouble": { 
     "$ref": "MyGenericClassDouble" 
    }, 
    "genNulableDouble": { 
     "$ref": "MyGenericClassNullableDouble" 
    } 
    } 
} 

작동하지만 참조는 정의를 제대로 참조하지 않습니다.

답변

0

저는 올바른 길을 가고 있다고 생각합니다. StringEnumGenerationProvider 대신에 JSchemaGenerationProvider을 직접 구현해야한다고 생각합니다. creating a custom provider 식으로 뭔가 :

public class FormatSchemaProvider : JSchemaGenerationProvider 
{ 
    public override JSchema GetSchema(JSchemaTypeGenerationContext context) 
    { 
     // customize the generated schema for these types to have a format 
     if (context.ObjectType == typeof(MyGenericClass<bool>)) 
     { 
      return CreateSchemaWithFormat(
       context.ObjectType, context.Required, "MyGenericClass"); 
     } 
     // use default schema generation for all other types 
     return null; 
    } 

    private JSchema CreateSchemaWithFormat(Type type, Required required, string format) 
    { 
     JSchemaGenerator generator = new JSchemaGenerator(); 
     JSchema schema = generator.Generate(type, required != Required.Always); 
     schema.Format = format; 
     return schema; 
    } 
} 

그런 다음 새로운 세대 공급자를 추가는 :

JSchemaGenerator generator = new JSchemaGenerator(); 
generator.GenerationProviders.Add(new FormatSchemaProvider()); 
JSchema schema = generator.Generate(typeof(MyClass)); 
+0

이 정의 항목을 변경하지 않습니다. { "MyGenericClass "{ "타입"[ "개체" "NULL" ] "속성"{ "소유"그냥 "포맷" "정의"를 추가 { "유형": "부울" } }, "필수"[ "소유" , "형식": "MyGenericClass" } } 나는 "정의"를 만들 필요가 – Yoztastic

+0

: { "MyGenericClass "은"정의 "가됩니다 : {"MyGenericClassBoolean "및 모든 속성은 동일한 이름, 즉"속성 "을 참조합니다. { "세대": { "$ 심판": "#/정의/MyGenericClass " 은} "속성"이되어야 { "세대": { "$ 심판": "#/정의/MyGenericClassBoolean" } – Yoztastic

+0

@Yoztastic - ['CustomConverter'] (https://www.newtonsoft.com/json/help/html/CustomJsonConverter.htm)이 필요할 것입니다. – SwDevMan81