System.Json.Net - deserializing a Task<T> fails (no parameterless constructor)
Asked Answered
A

1

0

I'm running into a problem where I can't deserialize a string into a Task using System.Text.Json (.Net 5).

JsonSerializer.Deserialize<Task<TItem>>(serializedItem)

Background

I have a localized cache and store in it items retrieved from the DB.

I can't store the actual item in the cache, because any subsequent manipulation of the object results in the cached item being manipulation, affecting all further uses. I therefore store a serialized copy of the object.

Regarding performance...

I'm using the async/await pattern to call the DB (the whole app is async).

I read an article (may have been a video) in which Stephen Toub described the performance advantage of caching the Task. This SO article When to cache Tasks? goes into the details. Anyhow, I thought I'd try to take advantage of this (it works perfectly without serialization) using the following in my local cache "layer":

  1. If Task is in my cache, await it and return the result.
  2. Otherwise, call the DB method without awaiting it and add the resultant task to the cache

When I add serialization, then the deserialization of the task:

Task<TItem>? cachedItem = JsonSerializer.Deserialize<Task<TItem>>(serializedItem);

results in

Deserialization of types without a parameterless constructor, a singular parameterized constructor, or a parameterized constructor annotated with 'JsonConstructorAttribute' is not supported.

Aronarondel answered 25/9, 2020 at 7:16 Comment(4)
How is this related to async-await? Does it work if it's synchronous?Lai
You can't serialize or deserialize a Task<T>, it is an operation that returns its result asynchronously, not a data object from which a meaningful contract can be derived. It wraps an Action<T> or other delegate, and you can't serialize a delegate. See: how come BinaryFormatter can serialize an Action<> but Json.net cannot. Of course that answer is for json.net, but system.text.json is even more limited and doesn't even attempt to support [Serializable] serialization, as it doesn't serialize members, only properties.Pharaoh
And while Action<T> is technically marked as [Serializable], Task<T> is not, so there's no reason to think it could be serialized.Pharaoh
Is that sufficient for an answer?Pharaoh
D
0

The answer here is relatively straightforward - serialize the data inside the Task result, not the task itself.

If you aren't using something like memcached but rather using something like a simple Dictionary in-process object cache then serializing and deserializing seems like a rather heavy approach to cloning objects though.

Demers answered 2/12, 2020 at 7:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.