0

I need to write ExtensionParsers for OpenApi.NET, so that when I parse a yaml document, the extension properties (properties named x-something) are parsed into the corresponding C# classes that I wrote instead of being parsed generally into OpenApiObject.

So for example, when I use OpenApi.NET to parse the following yaml document:

openapi: 3.0.2
info:
  title: 'My interface'
  version: '1.0'
servers:
  - url: https://www.example.com
paths:
  "/student":
    get:
      parameters:
      - name: school
        in: query
        schema:
          type: string
      x-setting:
        name: 'Hello world'
        number: 312
        device: mobile
      responses:
        "200":
          description: Successful
          headers:
            Content-Type:
              schema:
                type: string
          content:
            application/json:
              schema:
                type: string

the parameter object is parsed to a C# object of type OpenApiParameter, name is of type string, In is an enum of type ParameterLocation and schema is of type OpenApiSchema.

But x-setting is parsed to a C# object of type OpenApiObject, name is parsed as OpenApiString, number is parsed as OpenApiInteger and device as OpenApiString.

But as I already have the following c# class:

class Setting
    {
        string Name;
        int Number;
        Device Device;
    }

I want it to be parsed to a C# object of type Setting, name as string, number as integer and device as an enum of type Device. Exactly like the parameter object.

It is mentioned here that this can be done using the property ExtensionParsers. But it is not clear how.

There are no docs and the explanation in comments in code is not so good. So could someone help on this?

Many thanks.

user9514066
  • 119
  • 1
  • 11

1 Answers1

0

You need to provide an extension parser to do the transformation from the OpenApiObject to the native C# class. e.g.

 var settings = new OpenApiReaderSettings()
            {
                ExtensionParsers = { { "x-foo", (a,v) => {
                        var fooNode = (OpenApiObject)a;
                        return new FooExtension() {
                              Bar = (fooNode["bar"] as OpenApiString)?.Value,
                              Baz = (fooNode["baz"] as OpenApiString)?.Value
                        };
                } } }
            };

https://github.com/microsoft/OpenAPI.NET/blob/3aeeef600d19e4ecfdf0d116725658b1c496eba0/test/Microsoft.OpenApi.Readers.Tests/TestCustomExtension.cs#L29

Sorry there are not docs, I unfortunately just have not had time.

Darrel Miller
  • 139,164
  • 32
  • 194
  • 243
  • Brilliant! And if the type of baz for example were OpenApiParameter instead of OpenApiString, how can I make it parse correctly to an object of type OpenApiParameter instead of OpenApiObject? I tried to cast it like we do with OpenApiString but it didn't work. – user9514066 Jan 29 '20 at 16:42
  • @user9514066 That's an interesting scenario. I'm not sure we have a really efficient way of doing it. However, we can probably build casting operators that can translate OpenApiObjects into other OpenApiXXX types. There is a way of doing this more efficiently but it would require making public the node types that are currently internal. – Darrel Miller Jan 30 '20 at 01:59