Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] Deserialization Cannot Handle Types with Constructors with Optional Parameters #726

Open
JCKortlang opened this issue Jul 23, 2024 · 3 comments
Labels
bug Something isn't working

Comments

@JCKortlang
Copy link

What is the bug?

Deserialization Cannot Handle Types with Constructors with Optional Parameters

System.Exception: Cannot create an instance of System.Text.Json.Nodes.JsonObject because it does not have a public constructor accepting IDictionary<System.String,System.Text.Json.Nodes.JsonNode> argument or a public parameterless constructor
   at OpenSearch.Client.InterfaceGenericDictionaryResolver.DictionaryFormatterHelper.GetFormatter(Type t)
   at OpenSearch.Client.InterfaceGenericDictionaryResolver.FormatterCache`1..cctor()

Specifically, new JsonObject() is valid but fatals the deserialziation code. The result is we cannot deserialize to a JsonObject

    //Given
    public JsonObject(JsonNodeOptions? options = null)
      : base(options)
    {
    }

How can one reproduce the bug?

using System.Text.Json.Nodes
return await openSearchClient.SearchAsync<JsonObject>(searchRequest);

What is the expected behavior?

I expect to be able to deserialize to standard .NET Json abstractions

What is your host/environment?

MacOS 13.6.7 (22G720)

Do you have any screenshots?

No

Do you have any additional context?

I am attempting to deserialize a request to an index alias that contains multiple types. Since the Search interface does not support this, I need to deserialize the response to a more generic type. Ideally one of the standard and existing Json abstractions.

@JCKortlang JCKortlang added bug Something isn't working untriaged labels Jul 23, 2024
@Xtansia Xtansia removed the untriaged label Jul 23, 2024
@Xtansia
Copy link
Collaborator

Xtansia commented Jul 23, 2024

Hi @JCKortlang,

System.Text.Json is not yet supported or used by the library (see #388), and as these generic JsonObject/JsonNode types usually require special handling rather than being treated as plain objects I don't believe that fixing the constructor issue would solve your issue.

You should be able to use dynamic/DynamicObject as the document type to handle unspecified structures. Alternatively there is also an implementation for using Newtonsoft

@JCKortlang
Copy link
Author

Hello @Xtansia,

I did read through that issue. My main intent was to point out the constructor constraint causes issues. Unclear if this is intended / expected for constructors with optional parameters.

public record Foo
{
  //Would also fail?
  public Foo(object? optional = null)
  {
     
  }
}

Is there a mechanism to receive Document as a byte array or a value that has not been deserialized? The intent is to save the initial deserialization cost. Should I create a separate issue?

@Xtansia
Copy link
Collaborator

Xtansia commented Jul 23, 2024

Yes the constructor issue is valid, will need to see how it compares in scope/effort/priority wise against the fact we intend to throw away the current JSON serialisation and move to System.Text.Json in the future.

The way to skip all deserialisation is to use the generic http methods, using BytesResponse or StringResponse like so:

var resp = await client.Http.PostAsync<BytesResponse>(
    $"/{IndexName}/_search",
    r => r.SerializableBody(new SearchDescriptor<object>()
        .Query(q => q.MatchAll())
        .Size(20)));

var bytes = resp.Body;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants