Skip to content

Issues with v2 (possible v3 also) spec reading channel utilizing parameter with referenced enum #14

@Nikolajls

Description

@Nikolajls

Describe the bug

I'm working with an async specifcation that i'm trying to read using the library.
However I'm getting a null reference exception at somepoint when deserializing it - I've tried for a few hours to go through the library code and understand how it works

It creates a AsyncApiJsonSchemaReference which Workspace is null making all of this return null and assign that to the target
Which makes schema.Enum throw the nullreference exception
However im not grasping how the Workspace ideally should be set in this case

To Reproduce

Steps to reproduce the behavior:

  1. Create a document with 'sample document below'
  2. Try to change to 'use the other value'
  3. Try to validate the document doing 'deserializing the channel parameter' at AsyncApiParameterDeserializer.cs:26
  4. See error

Expected behavior

To be able to deserialze and work with the AsyncApiDocument afterwards

Sample document

If applicable, add an AsyncAPI document illustrating the problem.
Reproducable json that fails, but works on AsyncAPI studio and also to my understanding of the specification.

{
    "asyncapi": "2.6.0",
    "info": {
        "title": "NikolajApi",
        "description": "Trying to work with enum in parameter",
        "contact": {
            "url": "https://github.com/Nikolajls",
            "name": "Nikolaj",
            "email": "test@test.com"
        },
        "version": "0.0.1"
    },
    "servers": {
        "integration-pulsar": {
            "url": "pulsar+ssl://localhost:6651",
            "protocol": "pulsar+ssl"
        }
    },
    "channels": {
        "v1.Room.{roomId}.Opened": {
            "publish": {
                "description": "Publish a message about a room being opened",
                "operationId": "pub-room",
                "message": {
                    "$ref": "#/components/messages/RoomOpened"
                }
            },
            "parameters": {
                "roomId": {
                    "schema": {
                        "$ref": "#/components/schemas/Rooms"
                    },
                    "description": "The ID of the room"
                }
            }
        }
    },
    "components": {
        "schemas": {
            "RoomOpened": {
                "type": "object",
                "properties": {
                    "roomName": {
                        "type": "string",
                        "examples": [
                            "ABC"
                        ]
                    }
                },
                "additionalProperties": false
            },
            "Rooms": {
                "enum": [
                    "123",
                    "245",
                    "678"
                ],
                "type": "string"
            }
        },
        "messages": {
            "RoomOpened": {
                "name": "RoomOpened",
                "summary": "Message indicating a room has been opened",
                "contentType": "application/json",
                "payload": {
                    "$ref": "#/components/schemas/RoomOpened"
                }
            }
        }
    }
}

Screenshots

If applicable, add screenshots to help explain your problem.

Image
Image

Additional context

By modifying the spec and removing the reference so the roomid schema has the enum directly it works.

Modified spec without the reference:

{
    "asyncapi": "2.6.0",
    "info": {
        "title": "NikolajApi",
        "description": "Trying to work with enum in parameter",
        "contact": {
            "url": "https://github.com/Nikolajls",
            "name": "Nikolaj",
            "email": "test@test.com"
        },
        "version": "0.0.1"
    },
    "servers": {
        "integration-pulsar": {
            "url": "pulsar+ssl://localhost:6651",
            "protocol": "pulsar+ssl"
        }
    },
    "channels": {
        "v1.Room.{roomId}.Opened": {
            "publish": {
                "description": "Publish a message about a room being opened",
                "operationId": "pub-room",
                "message": {
                    "$ref": "#/components/messages/RoomOpened"
                }
            },
            "parameters": {
                "roomId": {
                    "schema": {
                        "enum": [
                            "123",
                            "245",
                            "678"
                        ],
                        "type": "string"
                    },
                    "description": "The ID of the room"
                }
            }
        }
    },
    "components": {
        "schemas": {
            "RoomOpened": {
                "type": "object",
                "properties": {
                    "roomName": {
                        "type": "string",
                        "examples": [
                            "ABC"
                        ]
                    }
                },
                "additionalProperties": false
            }
        },
        "messages": {
            "RoomOpened": {
                "name": "RoomOpened",
                "summary": "Message indicating a room has been opened",
                "contentType": "application/json",
                "payload": {
                    "$ref": "#/components/schemas/RoomOpened"
                }
            }
        }
    }
}

stack trace of the issue happening:

System.ArgumentNullException : Value cannot be null. (Parameter 'source')
   at System.Linq.ThrowHelper.ThrowArgumentNullException(ExceptionArgument argument)
   at System.Linq.Enumerable.TryGetNonEnumeratedCount[TSource](IEnumerable`1 source, Int32& count)
   at System.Linq.Enumerable.Any[TSource](IEnumerable`1 source)
   at ByteBard.AsyncAPI.Readers.AsyncApiV2Deserializer.LoadParameterFromSchema(AsyncApiParameter instance, ParseNode node) in C:\Users\dkNiLuSo\DEV\Development\Git\AsyncAPI.NET\src\ByteBard.AsyncAPI.Readers\V2\AsyncApiParameterDeserializer.cs:line 26
   at ByteBard.AsyncAPI.Readers.AsyncApiV2Deserializer.<>c.<.cctor>b__93_134(AsyncApiParameter a, ParseNode n) in C:\Users\dkNiLuSo\DEV\Development\Git\AsyncAPI.NET\src\ByteBard.AsyncAPI.Readers\V2\AsyncApiParameterDeserializer.cs:line 13
   at ByteBard.AsyncAPI.Readers.ParseNodes.PropertyNode.ParseField[T](T parentInstance, IDictionary`2 fixedFields, IDictionary`2 patternFields) in C:\Users\dkNiLuSo\DEV\Development\Git\AsyncAPI.NET\src\ByteBard.AsyncAPI.Readers\ParseNodes\PropertyNode.cs:line 62
   at ByteBard.AsyncAPI.Readers.AsyncApiV2Deserializer.ParseMap[T](MapNode mapNode, T domainObject, FixedFieldMap`1 fixedFieldMap, PatternFieldMap`1 patternFieldMap) in C:\Users\dkNiLuSo\DEV\Development\Git\AsyncAPI.NET\src\ByteBard.AsyncAPI.Readers\V2\AsyncApiDeserializer.cs:line 25
   at ByteBard.AsyncAPI.Readers.AsyncApiV2Deserializer.LoadParameter(ParseNode node) in C:\Users\dkNiLuSo\DEV\Development\Git\AsyncAPI.NET\src\ByteBard.AsyncAPI.Readers\V2\AsyncApiParameterDeserializer.cs:line 54
   at ByteBard.AsyncAPI.Readers.ParseNodes.MapNode.<>c__DisplayClass7_0`1.<CreateMap>b__0(KeyValuePair`2 n) in C:\Users\dkNiLuSo\DEV\Development\Git\AsyncAPI.NET\src\ByteBard.AsyncAPI.Readers\ParseNodes\MapNode.cs:line 105
   at System.Linq.Enumerable.SelectEnumerableIterator`2.MoveNext()
   at System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector, IEqualityComparer`1 comparer)
   at System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector)
   at ByteBard.AsyncAPI.Readers.ParseNodes.MapNode.CreateMap[T](Func`2 map)
   at ByteBard.AsyncAPI.Readers.AsyncApiV2Deserializer.<>c.<.cctor>b__93_4(AsyncApiChannel a, ParseNode n) in C:\Users\dkNiLuSo\DEV\Development\Git\AsyncAPI.NET\src\ByteBard.AsyncAPI.Readers\V2\AsyncApiChannelDeserializer.cs:line 19
   at ByteBard.AsyncAPI.Readers.ParseNodes.PropertyNode.ParseField[T](T parentInstance, IDictionary`2 fixedFields, IDictionary`2 patternFields) in C:\Users\dkNiLuSo\DEV\Development\Git\AsyncAPI.NET\src\ByteBard.AsyncAPI.Readers\ParseNodes\PropertyNode.cs:line 62
   at ByteBard.AsyncAPI.Readers.AsyncApiV2Deserializer.ParseMap[T](MapNode mapNode, T domainObject, FixedFieldMap`1 fixedFieldMap, PatternFieldMap`1 patternFieldMap) in C:\Users\dkNiLuSo\DEV\Development\Git\AsyncAPI.NET\src\ByteBard.AsyncAPI.Readers\V2\AsyncApiDeserializer.cs:line 25
   at ByteBard.AsyncAPI.Readers.AsyncApiV2Deserializer.LoadChannel(ParseNode node, String channelAddress) in C:\Users\dkNiLuSo\DEV\Development\Git\AsyncAPI.NET\src\ByteBard.AsyncAPI.Readers\V2\AsyncApiChannelDeserializer.cs:line 42
   at ByteBard.AsyncAPI.Readers.AsyncApiV2Deserializer.<>c.<.cctor>b__93_45(MapNode n2, String originalKey) in C:\Users\dkNiLuSo\DEV\Development\Git\AsyncAPI.NET\src\ByteBard.AsyncAPI.Readers\V2\AsyncApiDocumentDeserializer.cs:line 22
   at ByteBard.AsyncAPI.Readers.ParseNodes.MapNode.<>c__DisplayClass6_0`1.<CreateMap>b__0(KeyValuePair`2 n) in C:\Users\dkNiLuSo\DEV\Development\Git\AsyncAPI.NET\src\ByteBard.AsyncAPI.Readers\ParseNodes\MapNode.cs:line 70
   at System.Linq.Enumerable.SelectEnumerableIterator`2.MoveNext()
   at System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector, IEqualityComparer`1 comparer)
   at System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector)
   at ByteBard.AsyncAPI.Readers.ParseNodes.MapNode.CreateMap[T](Func`2 keySelector, Func`3 map)
   at ByteBard.AsyncAPI.Readers.AsyncApiV2Deserializer.<>c.<.cctor>b__93_41(AsyncApiDocument a, ParseNode n) in C:\Users\dkNiLuSo\DEV\Development\Git\AsyncAPI.NET\src\ByteBard.AsyncAPI.Readers\V2\AsyncApiDocumentDeserializer.cs:line 21
   at ByteBard.AsyncAPI.Readers.ParseNodes.PropertyNode.ParseField[T](T parentInstance, IDictionary`2 fixedFields, IDictionary`2 patternFields) in C:\Users\dkNiLuSo\DEV\Development\Git\AsyncAPI.NET\src\ByteBard.AsyncAPI.Readers\ParseNodes\PropertyNode.cs:line 62
   at ByteBard.AsyncAPI.Readers.AsyncApiV2Deserializer.ParseMap[T](MapNode mapNode, T domainObject, FixedFieldMap`1 fixedFieldMap, PatternFieldMap`1 patternFieldMap) in C:\Users\dkNiLuSo\DEV\Development\Git\AsyncAPI.NET\src\ByteBard.AsyncAPI.Readers\V2\AsyncApiDeserializer.cs:line 25
   at ByteBard.AsyncAPI.Readers.AsyncApiV2Deserializer.LoadAsyncApi(RootNode rootNode) in C:\Users\dkNiLuSo\DEV\Development\Git\AsyncAPI.NET\src\ByteBard.AsyncAPI.Readers\V2\AsyncApiDocumentDeserializer.cs:line 58
   at ByteBard.AsyncAPI.Readers.V2.AsyncApiV2VersionService.LoadDocument(RootNode rootNode) in C:\Users\dkNiLuSo\DEV\Development\Git\AsyncAPI.NET\src\ByteBard.AsyncAPI.Readers\V2\AsyncApiV2VersionService.cs:line 79
   at ByteBard.AsyncAPI.Readers.ParsingContext.Parse(JsonNode jsonNode) in C:\Users\dkNiLuSo\DEV\Development\Git\AsyncAPI.NET\src\ByteBard.AsyncAPI.Readers\ParsingContext.cs:line 89
   at ByteBard.AsyncAPI.Readers.AsyncApiJsonDocumentReader.Read(JsonNode input, AsyncApiDiagnostic& diagnostic) in C:\Users\dkNiLuSo\DEV\Development\Git\AsyncAPI.NET\src\ByteBard.AsyncAPI.Readers\AsyncApiJsonDocumentReader.cs:line 59
   at ByteBard.AsyncAPI.Readers.AsyncApiTextReader.Read(TextReader input, AsyncApiDiagnostic& diagnostic) in C:\Users\dkNiLuSo\DEV\Development\Git\AsyncAPI.NET\src\ByteBard.AsyncAPI.Readers\AsyncApiTextReader.cs:line 52
   at ByteBard.AsyncAPI.Readers.AsyncApiStringReader.Read(String input, AsyncApiDiagnostic& diagnostic) in C:\Users\dkNiLuSo\DEV\Development\Git\AsyncAPI.NET\src\ByteBard.AsyncAPI.Readers\AsyncApiStringReader.cs:line 31
   at ByteBard.AsyncAPI.Tests.AsyncApiReaderTests.V2_Read_WithComponentBindings_Deserializes() in C:\Users\dkNiLuSo\DEV\Development\Git\AsyncAPI.NET\test\ByteBard.AsyncAPI.Tests\AsyncApiReaderTests.cs:line 50
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
   at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions