JsonConverterFactory equivalent?

Hi,

The question: is there any mechanism existing or planned in ServiceStack.Text which gives similar capabilities to those found in System.Text.Json.Serialization.JsonConverterFactory?

For various business reasons which aren’t really relevant to the question (mostly in that I can’t change them), I find myself in a situation where:

  1. I have numerous different POCOs which represent specific types of entities. These POCOs can be complex.
  2. Some of the POCOs in #1 contain collections of other of these POCOs (i.e., an arbitrary tree of these types)
  3. I need a variety of collections of these POCOs, but unfortunately I can’t easily wrap them in collection types ServiceStack seems to natively understand. Instead, they need to be in a collection of our internal specification with specific business-relevant properties
  4. I need to (de)serialize these types and their collections to/from JSON.

In other parts of the system that must use System.Text.Json.Serialization.JsonConverterFactory, I’ve been able to easily use a single JsonConverterFactory which accomplishes this.

Right now, for the ServiceStack part which uses these types, the only solution I’ve found is to have many dozens entries for JSConfig which all look similar to:

JsConfig<MyCollectionType<MyPocoTypeX>>.RawDeserializeFn = s => JsonSerializer.DeserializeFromString<List<MyPocoTypeX>>(s).ToMyCollectionType();

JsConfig<MyCollectionType<MyPocoTypeY>>.RawDeserializeFn = s => JsonSerializer.DeserializeFromString<List<MyPocoTypeY>>(s).ToMyCollectionType();

I do understand I could build an entirely separate parallel hierarchy of all these types which contain the MyPoco types, NOT use the MyCollectionType, and instead use List so ServiceStack is comfortable deserializing them, and then automap, but that seems even more painful than just using dozens of RawDeserializerFns

I suppose I could also do some reflection trickery to automatically find all the uses of MyCollection and then dynamically build appropriate RawDeserializeFn methods…but really, it seems what I need a JsonConverterFactory like is provided in System.Text.Json.Serialization.JsonConverterFactory

Any thoughts?

Thanks!

EDIT:
Here’s a link to the Microsoft documentation for the JsonConverterFactory, for those who haven’t run across this before

Given I’ve never heard of JsonConverterFactory, ServiceStack.Text wont have anything like it. The only customizations available are going to be what’s documented in JSON format docs.

Why isn’t it enough to just configure JsConfig<MyPocoTypeX>? Why does it need to also configure collection types referencing it, do they not implement IEnumerable<T>?

If the available customizations aren’t sufficient you may be able to use object where they’ll be parsed into non-generic collections using JS Utils which you can later to use to convert into these types.

But I’d really avoid pushing this complexity down to all serializers and instead map them to Serializable DTOs that match the wire format you want to send and use built-in AutoMapping to convert them into these non-serializable types you want them in.

Thanks for the quick response as always! Pardon my oversight for not including a link to the Microsoft doc in question around their implementation of the factory pattern for JSON converters.

I was initially hoping I could indeed simply register a JsConfig<MyPocoTypeX> however that did not work - it appears the problem is that the type is contained in an open generic like my MyCollectionType and ServiceStack of course doesn’t know how to construct those.

Unfortunately my domain is fiendishly complicated (and irreducible) and therefore there are about 100 different MyPocoTypes which can be contained in the MyCollectionType. These entities are already in DTOs (and are serialized in other places like in messages used with MassTransit). Luckily MassTransit 8 uses System.Text.Json.Serialization so I can use their JsonConverter factory.

If there’s no lower-touch option than what I’ve already come up with (a one-liner per contained type) I’ll just stick with that and possibly explore a reflection-based mechanism to set these up…but maybe others have need for deserializing open generic collections too and so in the future you could consider a factory pattern for these deserializers.

1 Like

Issue with needing to rely on advanced serializer features is that it effectively binds those models to a single serializer impl + configuration where they’ll be unsupported in other API Serializers/endpoints and even incompatible with all other JSON serializers and all API clients that aren’t using the exact serializer impl + configuration which isn’t what you want in an API.

But the best place to propose new features is in GitHub Discussions with an example use-case where it’s recorded and others can vote + collaboratively discuss it:

https://servicestack.net/ideas

That all makes sense, particular the implications for the other API serializers, endpoints, and clients.

Thanks for the replies. I’ll just roll with this for now.

1 Like