question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

An error "JSON cannot deserialize the given value." when use Federation and JsonType properties in the models of internal service

See original GitHub issue

Is there an existing issue for this?

  • I have searched the existing issues

Product

Hot Chocolate

Describe the bug

Hey guys. I have occured with strange behavior when using JsonType and federation. So I have model on the internal service:

public class MyModel
{
    public long Id { get; set; }

    [GraphQLType(typeof(JsonType))]
    public string MyJson{ get; set; }
}

MyJson actually is List<Hours>. But in database it is stored like json string.

public class Hours
{
    public DayOfWeek Day { get; set; }
    public bool IsActive { get; set; }
    public TimeSpan? From { get; set; }
    public TimeSpan? To { get; set; }
}

When I’m fetching MyModel directly from internal service - it works fine, I recieve normal json response, but when I’m trying to fetch data via my external service, that is stitched with internal one, it says “JSON cannot deserialize the given value.”

Steps to reproduce

  1. Configuration of internal service:
  • Model
public class MyModel
{
    public long Id { get; set; }

    [GraphQLType(typeof(JsonType))]
    public string MyJson{ get; set; }
}
  • Query
[QueryType]
public class MyModelQueries
{
    [UsePaging(IncludeTotalCount = true)]
    [UseProjection]
    [UseFiltering]
    [UseSorting]
    public IQueryable<MyModel> MyModelSearch([Service] IMyModelRepository repository)
    => repository.EntitySearch();
}
  • Startup
        services.AddMemoryCache();
        services.AddGraphQLServer()
                .AddServiceTypes()
                .AddType(new TimeSpanType(TimeSpanFormat.DotNet))
                .AddProjections()
                .AddFiltering()
                .AddSorting()
                .AddInMemorySubscriptions()
                .InitializeOnStartup()
                .PublishSchemaDefinition(c => c
                  .SetName("InternalService"));
  1. Configuration of external service:
  • Startup
        services.AddHttpClient(
            "InternalService",
            c => c.BaseAddress = new Uri($"{InternalServiceUrl}/graphql"))

        services.AddGraphQLServer()
                .AddRemoteSchema("InternalService")
                .AddType(new TimeSpanType(TimeSpanFormat.DotNet));
  1. Make query on external service with fetching MyJson, that leads to “JSON cannot deserialize the given value.” errror in response.

Relevant log output

No response

Additional Context?

Platform: .Net6 Database: PostgreSQL EFCore: Npgsql.EntityFrameworkCore.PostgreSQL 7.0.1 HotChocolate: 13.3.3

Version

13.3.3

Issue Analytics

  • State:closed
  • Created 2 months ago
  • Comments:5 (1 by maintainers)

github_iconTop GitHub Comments

4reactions
mvarendorffcommented, Aug 1, 2023

Given that Stitching is still very much at the forefront of the documentation, I feel like this is a bit harsh. Arguably, I am biased, since I am facing the same problems as OP but two YouTube videos aside there is nothing available on Fusion yet:

grafik

Is there really no chance this could be looked at?

2reactions
Vespersioncommented, Aug 3, 2023

I’ve also run into this issue, and given that it looks like this will never be looked at, and until Fusion has some better documentation and we can switch to it, I’ve found an intermediary solution.

In my case I was using the JSON type, with my underlying field being a JsonElement. What seems to be the problem is that the downstream service returns a JsonElement to the stitching request, but this response result is all serialized to a Dictionary, which means that the full JsonElement object is converted to a dictionary. In this case the stitching code doesn’t seem to handle this situation and can’t turn a dictionary into a JsonElement. I haven’t used a string with the Json type but I imagine the problem is the same.

I’ve created an IHttpStitchingRequestInterceptor to intercept the stitching response from the downstream service. Notably the OnReceivedResultAsync() method takes an IQueryResult argument which contains the data dictionary and returns an IQueryResult, which will override the result value with your returned value.

From here I just converted the dictionary representation of the JsonElement into an actual JsonElement and replaced the value in the result. Obviously the hard part here is finding the correct value in the result, but the method also takes an IQueryRequest which describes the query.

Extremely simplified code below(probably a better way to convert from Dictionary to JsonElement but in my case I know my Json value is not nested):

public class GatewayHttpStitchingRequestInterceptor : IHttpStitchingRequestInterceptor
{
    public GatewayHttpStitchingRequestInterceptor()
    {
    }

    public ValueTask OnCreateRequestAsync(string targetSchema, IQueryRequest request, HttpRequestMessage requestMessage, CancellationToken cancellationToken = default)
    {
        return default;
    }

    public ValueTask<IQueryResult> OnReceivedResultAsync(string targetSchema, IQueryRequest request, IQueryResult result, HttpResponseMessage responseMessage, CancellationToken cancellationToken = default)
    {
        var entity = ((Dictionary<string, object>)result.Data["myEntity"]);
        var jsonValueDict = ((Dictionary<string, object>)entity["jsonField"]).ToDictionary(x => x.Key, x => ((IValueNode)x.Value).Value);
        var jsonValue = JsonSerializer.SerializeToDocument<Dictionary<string, object>>(jsonValueDict).RootElement;
        entity["jsonField"] = jsonValue;
        return new ValueTask<IQueryResult>(result);
    }
}
// Startup.cs

services.AddSingleton<IHttpStitchingRequestInterceptor, GatewayHttpStitchingRequestInterceptor>();

If my solution doesn’t exactly solve your problem, you can at least use the stitching interceptor to debug what might be wrong with the result.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Cannot deserialize the current JSON object (e.g. {"name": ...
Hi, Getting the below error when I am using “Deserialize JSON” activity ... {“name”:“value”}) into type 'UiPath.Service.Api.Service.Models.
Read more >
Cannot deserialize the current JSON array. - Microsoft Q&A
To fix this error either change the JSON to a JSON object (e.g. {"name":"value"}) or change the deserialized type to an array or...
Read more >
Polymorphic Deserialization throws if $type metadata isn't ...
Attempting to deserialize a polymorphic structure with System.Text.Json that doesn't feature $type at start of the object results in an ...
Read more >
Hibernate ORM 6.0.0.CR1 User Guide
The mutability of the value - whether the internal state can change like ... Hibernate will only use the JSON type if explicitly...
Read more >
JSON-LD 1.1
This specification defines JSON-LD 1.1, a JSON-based format to serialize Linked Data. The syntax is designed to easily integrate into deployed ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found