NJsonSchema
NJsonSchema copied to clipboard
How do I set the name of a property for the C# generator via a visitor?
My swagger looks like this
"OptionChainPair": {
"type": "object",
"properties": {
"optioncall": {
"xml": {
"name": "Call"
},
"description": "The option call in the option chain pair",
"$ref": "#/definitions/OptionDetails"
},
"optionPut": {
"xml": {
"name": "Put"
},
"description": "The option put in the option chain pair",
"$ref": "#/definitions/OptionDetails"
},
"pairType": {
"type": "string",
"description": "Determines whether the response will contain calls(CALLONLY), puts(PUTONLY), or both(CALLPUT)"
}
},
"xml": {
"name": "OptionPair"
}
}
Via https://apisb.etrade.com/docs/api/market/optionsjson/swagger.json
Any time I have an "xml": "name": "WhateverHere"
I need to use THAT for the key.
For example, the above JSON should look like this when generated to a C# model:
/// <summary>Container for an option pair; each option pair in the response has a container</summary>
[Newtonsoft.Json.JsonProperty("OptionPair", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
public System.Collections.Generic.List<OptionChainPair> OptionPairs { get; set; }
Not like this:
/// <summary>Container for an option pair; each option pair in the response has a container</summary>
[Newtonsoft.Json.JsonProperty("optionPairs", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
public System.Collections.Generic.List<OptionChainPair> OptionPairs { get; set; }
I have some code like this:
public class MyVisitor : JsonSchemaVisitorBase
{
protected override Task<JsonSchema4> VisitSchemaAsync(JsonSchema4 schema, string path, string typeNameHint)
{
if (schema is SwaggerParameter || schema is JsonProperty)
{
if (schema.Type == JsonObjectType.Object)
{
var schemaPropert = ((JsonProperty)schema);
schemaPropert.Name = schemaPropert.Xml.Name; // COMPILE ERROR: READONLY
foreach(var prop in schema.Properties)
{
prop.Value.Name = prop.Value.Xml.Name; // COMPILE ERROR: READONLY
}
}
}
}
return Task.FromResult(schema);
}
}
The code wont compile and I am not sure how to tweak those keys.
I use the following (not using a visitor):
public static class ConversionHelper
{
public static string ConvertToUpperCamelCase(string input, bool firstCharacterMustBeAlpha)
{
if (String.IsNullOrEmpty(input))
{
return String.Empty;
}
input = input.Replace(" ", "_").Replace("/", "_");
input = ConvertDashesToCamelCase(input[0].ToString().ToUpperInvariant() + input.Substring(1));
if (String.IsNullOrEmpty(input))
{
return String.Empty;
}
if (firstCharacterMustBeAlpha && char.IsNumber(input[0]))
{
return "_" + input;
}
return input;
}
private static string ConvertDashesToCamelCase(string input)
{
StringBuilder stringBuilder = new StringBuilder();
bool flag = false;
foreach (char c in input)
{
if (c == '-' || c == '_')
{
flag = true;
}
else if (flag)
{
stringBuilder.Append(char.ToUpperInvariant(c));
flag = false;
}
else
{
stringBuilder.Append(c);
}
}
return stringBuilder.ToString();
}
}
public class MyPropertyNameGenerator : IPropertyNameGenerator
{
string IPropertyNameGenerator.Generate(JsonProperty property)
{
return ConversionHelper.ConvertToUpperCamelCase(property.Name, true);
}
}
public class MyTypeNameGenerator : DefaultTypeNameGenerator
{
protected override string Generate(JsonSchema4 schema, string typeNameHint)
{
if (string.IsNullOrEmpty(typeNameHint) && !string.IsNullOrEmpty(schema.Title) && Regex.IsMatch(schema.Title, "^[a-zA-Z0-9_]*$"))
{
typeNameHint = schema.Title;
}
String name = ConversionHelper.ConvertToUpperCamelCase(typeNameHint?.Split('.').Last() ?? "Anonymous", true);
return name;
}
}
public void GenerateCode(JsonSchema4 schema)
{
CSharpGeneratorSettings settings = new CSharpGeneratorSettings();
settings.GenerateImmutableDictionaryProperties = true;
settings.GenerateImmutableArrayProperties = true;
settings.Namespace = "My.Namespace";
settings.PropertyNameGenerator = new MyPropertyNameGenerator();
settings.TypeNameGenerator = new MyTypeNameGenerator();
CSharpGenerator jobGenerator = new CSharpGenerator(schema, settings);
}
The Xml property: https://github.com/RSuter/NJsonSchema/blob/master/src/NJsonSchema/JsonSchema4.cs#L470
The JsonXmlObject name: https://github.com/RSuter/NJsonSchema/blob/master/src/NJsonSchema/JsonXmlObject.cs#L22
I'm wondering why the setter is internal? @emilw do you know that?
Hi @RicoSuter , Sorry for late response, i don't remember fully but it is most likely due to that it's just implemented for one way e.g. C# to Swagger spec. All these properties are created by that internal logic. I guess it should be safe to expose them, but again...there is no support for going the other way as i see it.
@VictorioBerra I'm sorry to bump the issue off-topic, but I'm too curious about how, and where did you obtain the ETrade swagger file link and if there are any more of them?
It's been a very long time so I do not fully remember. But if I recall when you get access to the etrade developer portal there are links there for it.