C
C#17mo ago
LPeter1997

❔ Avoid infinite recursion in STJ converters

There are so-so many cases where I only want to customize reading up a type in System.Text.Json, but I'd want the default behavior for writing. Currently I'm doing this to avoid SO:
public override void Write(Utf8JsonWriter writer, TInterface value, JsonSerializerOptions options)
{
// TODO: Ugly hack, can we avoid recursion in a nicer way?
// Remove this converter
var newOptions = new JsonSerializerOptions(options);
for (var i = options.Converters.Count - 1; i >= 0; --i)
{
if (options.Converters[i].GetType() == this.GetType()
|| options.Converters[i].GetType() == typeof(ModelInterfaceConverter))
{
newOptions.Converters.RemoveAt(i);
}
}

// Default behavior
JsonSerializer.Serialize(writer, value, newOptions);
}
public override void Write(Utf8JsonWriter writer, TInterface value, JsonSerializerOptions options)
{
// TODO: Ugly hack, can we avoid recursion in a nicer way?
// Remove this converter
var newOptions = new JsonSerializerOptions(options);
for (var i = options.Converters.Count - 1; i >= 0; --i)
{
if (options.Converters[i].GetType() == this.GetType()
|| options.Converters[i].GetType() == typeof(ModelInterfaceConverter))
{
newOptions.Converters.RemoveAt(i);
}
}

// Default behavior
JsonSerializer.Serialize(writer, value, newOptions);
}
This is janky as hell IMO, is there a better/nicer way? I've found no obvious answer to it.
16 Replies
ero
ero17mo ago
Well, you're not really meant to use JsonSerializer.Serialize in a converter. The whole idea of it is that you specify how things are serialized.
LPeter1997
LPeter1997OP17mo ago
Cool but that doesn't answer my question I don't want to specify how the given type is serialized, I only want to customize the reading part
ero
ero17mo ago
What...? Your post only ever talks about writing data, but now you ask about reading it?
LPeter1997
LPeter1997OP17mo ago
facepalm post is about avoiding all that BS in Write I have customized Reading To avoid SO, I have to remove my converter for writing, because I do want the default write behavior
There are so-so many cases where I only want to customize reading up a type in System.Text.Json, but I'd want the default behavior for writing. Currently I'm doing this to avoid SO
provides snippet with the obvious hack
is there a better/nicer way?
Please take your usual useless comments elsewhere 😅
ero
ero17mo ago
?
cap5lut
cap5lut17mo ago
when looking at all the different overloads i would guess thats exactly what to use to get back to the default behavior. so where is that information from so i can read up on the details on it? thb, this all sounds like u basically should just use different JsonSerializerOptions for serialization and deserialization in first place and let it throw NotSupportedException on Write (1) the type checks in there are a bit weird as well imo, if u want to write it like this, each converter should have to deal only with itself, the condition seems to take care of more which has imo to much of an side effect here (2) imo (1) would be the much cleaner way and it will also reduce the gc stress
LPeter1997
LPeter1997OP17mo ago
Yes, using different options for the 2 is pretty fair, I haven't thought about that I'll do that, thanks, it's essentially just one factory difference from reading The type-checks were in for safety tbh, since I didn't know if the converters made by the factory get inserted. Prolly not but I was paranoid, I had to test on an env where I had almost no way of debugging (and could repro there only...) Once I found the problem I left both in
cap5lut
cap5lut17mo ago
i think there should be even an reference equality check usable
LPeter1997
LPeter1997OP17mo ago
Likely yeah, I really don't know how factories behave in this case, I'll do some experimentation. But honestly, separating options just solves my problems as a whole
ero
ero17mo ago
it really depends on the data you're working with, but breaking up the converter into ones that have less responsibility may be an option.
record R(
[property: JsonConverter(...)] SomeType Foo,
SomeOtherType Bar);
record R(
[property: JsonConverter(...)] SomeType Foo,
SomeOtherType Bar);
instead of a converter on the entire record
cap5lut
cap5lut17mo ago
do u know what takes precedence here if u would have conflicting info on JsonSerializerOptions and the annotated version?
ero
ero17mo ago
hmm, conflicting? do you mean 2 different converters for the same type?
ero
ero17mo ago
what an inconsistent precedence
cap5lut
cap5lut17mo ago
(just saw if u scroll down a bit there, they even use JsonSerializer.Serialize() inside the Write() method theirself btw)
Accord
Accord17mo ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.
Want results from more Discord servers?
Add your server