Skip to content

AnyType omits values that are equal to values that are already written to the output #7227

Closed

Description

Product

Hot Chocolate

Version

13.9.6

Link to minimal reproduction

https://github.com/wietlol-org/HotChocolateIssues/tree/main/HotChocolateIssues.AnyTypeDataOmission

Steps to reproduce

Run the unit tests in the HotChocolateIssues.AnyTypeDataOmission project.
The test GetBooks will fail.
After running the tests, the output is written to the TestFiles folder where the erroneous response is presented.

What is expected?

When creating a query/mutation with output of type AnyType.
The data should all be present in the output.

What is actually happening?

Data that was already written to the output is omitted.

Given the following query definitions:

[GraphQLType<AnyType>]
public List<Book> GetBooksAny() =>
    GetBooks();

public List<Book> GetBooks() =>
[
    new Book(
        Title: "C# for dummies",
        Author: new Author(
            Name: "Jon Skeet"
        )
    ),
    new Book(
        Title: "Hot Chocolate: A .NET GraphQl server",
        Author: new Author(
            Name: "Michael Staib"
        )
    ),
    new Book(
        Title: "C# in depth.",
        Author: new Author(
            Name: "Jon Skeet"
        )
    ),
];

Running the following query:

query {
    books {
        title
        author {
            name
        }
    }
    
    booksAny
}

Gives the following output:

{
	"data": {
		"books": [
			{
				"title": "C# for dummies",
				"author": {
					"name": "Jon Skeet"
				}
			},
			{
				"title": "Hot Chocolate: A .NET GraphQl server",
				"author": {
					"name": "Michael Staib"
				}
			},
			{
				"title": "C# in depth.",
				"author": {
					"name": "Jon Skeet"
				}
			}
		],
		"booksAny": [
			{
				"title": "C# for dummies",
				"author": {
					"name": "Jon Skeet"
				}
			},
			{
				"title": "Hot Chocolate: A .NET GraphQl server",
				"author": {
					"name": "Michael Staib"
				}
			},
			{
				"title": "C# in depth."
			}
		]
	}
}

As you can see, the author is omitted in the booksAny output because the value is already present in the same output.
The equality is based on the class' implementation of Equals and HashCode, which for records is value-equality by default.
But this would be the same effect for any class/struct that has an implementation of Equals and HashCode that would consider it equal to another value that is in the output.

Looking at HotChocolate.Types.AnyType.cs line 151, the AnyType deliberately skips values that are already processed.
if (set.Add(value)) uses a HashSet<object> to check if the value was already processed.
This is probably added to prevent some form of recursive tree structure of generating an infinite recursion.
But this breaks the usage in the above example, where data is just not present and it becomes impossible to know what data should be there.

The output of books and booksAny should be the same.

Relevant log output

No response

Additional context

No response

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions