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.

TaskOrchestrator re-serializes message payload using Newtonsoft.Json.

See original GitHub issue

I get a JsonException when passing complex types from Orchestrator to Activity. The payload received in the TaskActivity is not compatible with System.Text.Json.

After investigation, it appears that the orchestrator re-serializes all messages using Newtonsoft.Json, with TypeNameHandling = TypeNameHandling.Objects. This results in a JSON payload that is not parseable using System.Text.Json (which is default for TaskActivity payload)

The class that does the conversion: https://github.com/Azure/durabletask/blob/main/src/DurableTask.Core/Serializing/JsonDataConverter.cs

Here is a sample project to demonstrate the issue: https://github.com/ulvesked/DurablePocoPayloadSample And a corresponding SO question: https://stackoverflow.com/questions/73776121/json-serialization-fails-with-functioninputconverterexception-for-complex-types

My original payload:

{
    "Name": "Test",
    "Items": [{
            "Id": "4b42d183-02c8-4108-b274-cde71f792832",
            "Image": "xH5hV...",
            "Thumbnail": "v8Tc3..."
       }, {
            "Id": "4eb034f6-eed0-4ad4-942d-c9bf20e465be",
            "Image": "wAj...",
            "Thumbnail": "juSiE",
        }
    ]
}

The payload received in TaskActivity:

{
    "Name": "Test",
    "Items": [{
            "$type": "DurablePocoPayloadSample.TestPayloadItem, DurablePocoPayloadSample",
            "Id": "4b42d183-02c8-4108-b274-cde71f792832",
            "Image": {
                "$type": "System.Byte[], System.Private.CoreLib",
                "$value": "xH5hV..."
            },
            "Thumbnail": {
                "$type": "System.Byte[], System.Private.CoreLib",
                "$value": "v8Tc3..."
            }
        }, {
            "$type": "DurablePocoPayloadSample.TestPayloadItem, DurablePocoPayloadSample",
            "Id": "4eb034f6-eed0-4ad4-942d-c9bf20e465be",
            "Image": {
                "$type": "System.Byte[], System.Private.CoreLib",
                "$value": "wAj..."
            },
            "Thumbnail": {
                "$type": "System.Byte[], System.Private.CoreLib",
                "$value": "juSiE..."
            }
        }
    ]
}

Issue Analytics

  • State:closed
  • Created a year ago
  • Comments:9 (1 by maintainers)

github_iconTop GitHub Comments

2reactions
jviaucommented, Sep 21, 2022

@plamber to fully replace the converter in DurableTask, there are a several locations you need to perform that:

  1. In the constructor of TaskHubClient
  2. Property on AsyncTaskActivity<TInput, TResult>
    • It is a protected set, so you can derive another interface ISettableDataConverter which has a method or property to set the data converter. Make sure all your activities implement this, then add a middleware to the DTFx pipeline to retrieve the current activity, attempt a cast to this, and set it.
  3. Property on TaskOrchestration<TResult, TInput, TEvent, TStatus>
    • Again a protected set, so use the same steps as AsyncTaskActivity in point 2
  4. Properties on OrchestrationContext (MessageDataConverter and ErrorDataConverter).
    • You might be able to also set this in middleware, can’t remember if you have access to this object there. Otherwise, you would need to derive your own base classes that implement the various TaskOrchestration types, and add a new step as part of its run method to set these properties on the context before calling the derived implementation.
1reaction
ulveskedcommented, Sep 21, 2022

Thanks for your comments. I have worked around the issue by using my own ObjectSerializer.

services.Configure<WorkerOptions>(opts => opts.Serializer = new MyNewtonsoftJsonObjectSerializer());

https://gist.github.com/ulvesked/44a6fc30d8fd622671343100eef8f1ae

I will keep it like this until the next preview, which hopefully has implemented the same serializer across the pipeline as @jviau wrote.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Migrate from Newtonsoft.Json to System.Text.Json - .NET
Newtonsoft.Json can serialize or deserialize numbers represented by JSON strings (surrounded by quotes). For example, it can accept: {" ...
Read more >
Deserializing JSON with Newtonsoft, using a specific class
Copy your JSON. Open Visual studio. Create new C# class file. Now Select below menu option: Edit > Paste Special > Paste JSON...
Read more >
Decoding and parsing JSON using NewtonSoft
Here are three ways you can access your data using the NewtonSoft JSON NuGet package. Deserialize the JSON message to a C# Class...
Read more >
Should you use Newtonsoft.Json or System.Text. ...
In the above example, there is clearly a mixing of concerns by conflating a request and its payload. This breaks many best-practice design ......
Read more >
How to create a custom converter that then calls the default ...
I am writing a custom converter for a type, let's say type X. In my ... In my case I needed to check...
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