C
C#2y ago
Sh1be

✅ System.Text.Json serialization problem

hello, I am using System.Text.Json. I have a struct that has 2 properties: a bool IsDefined and a T value. IsDefined gets set to true when value gets set. This is a container for properties that don't necessarily need to be set, but if they are set, they will get included in the serialization. The problem is that in the Write method, STJ automatically writes out the property name, which results in this Json if only the name property is set: {"name":"lol","parent_id":"position":}. The STJ write method:
if (!value.IsDefined) return;

switch (value.Value)
{
case long:
if (value.Value != null) writer.WriteStringValue(value.Value.ToString());
else writer.WriteNullValue();
break;

case ulong:
if (value.Value != null) writer.WriteStringValue(value.Value.ToString());
else writer.WriteNullValue();
break;

default:
writer.WriteRawValue(JsonSerializer.Serialize(value.Value));
break;
}
if (!value.IsDefined) return;

switch (value.Value)
{
case long:
if (value.Value != null) writer.WriteStringValue(value.Value.ToString());
else writer.WriteNullValue();
break;

case ulong:
if (value.Value != null) writer.WriteStringValue(value.Value.ToString());
else writer.WriteNullValue();
break;

default:
writer.WriteRawValue(JsonSerializer.Serialize(value.Value));
break;
}
How can I get around this?
121 Replies
Sh1be
Sh1be2y ago
this sadly doesn't work for my use case because it works like this: - value set - value is a normal value --> serialize - value null / default --> serialize - value not set --> don't serialize I want to check whether .IsDefined is true. how would I be able to do that?
deluvas
deluvas2y ago
https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/converters-how-to?pivots=dotnet-7-0 you could write a own jsonconverter for that class and use it with the system.text.json jsonserializer, then you could handle yourself how you want it to behave
Sh1be
Sh1be2y ago
I have that right now
internal class IgnorableConverter<T> : JsonConverter<Ignorable<T>>
{
public override Ignorable<T> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
throw new NotImplementedException();
}

public override void Write(Utf8JsonWriter writer, Ignorable<T> value, JsonSerializerOptions options)
{
if (!value.IsDefined) return;

switch (value.Value)
{
case long:
if (value.Value != null) writer.WriteStringValue(value.Value.ToString());
else writer.WriteNullValue();
break;

case ulong:
if (value.Value != null) writer.WriteStringValue(value.Value.ToString());
else writer.WriteNullValue();
break;

default:
writer.WriteRawValue(JsonSerializer.Serialize(value.Value));
break;
}
}
}
internal class IgnorableConverter<T> : JsonConverter<Ignorable<T>>
{
public override Ignorable<T> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
throw new NotImplementedException();
}

public override void Write(Utf8JsonWriter writer, Ignorable<T> value, JsonSerializerOptions options)
{
if (!value.IsDefined) return;

switch (value.Value)
{
case long:
if (value.Value != null) writer.WriteStringValue(value.Value.ToString());
else writer.WriteNullValue();
break;

case ulong:
if (value.Value != null) writer.WriteStringValue(value.Value.ToString());
else writer.WriteNullValue();
break;

default:
writer.WriteRawValue(JsonSerializer.Serialize(value.Value));
break;
}
}
}
but if it gets into the Write method the property name will automatically be written out.
[JsonPropertyName("name")]
public Ignorable<string> Name { get; init; }

[JsonPropertyName("parent_id")]
public Ignorable<ulong?> ParentId { get; init; }

[JsonPropertyName("position")]
public Ignorable<uint> Position { get; init; }
[JsonPropertyName("name")]
public Ignorable<string> Name { get; init; }

[JsonPropertyName("parent_id")]
public Ignorable<ulong?> ParentId { get; init; }

[JsonPropertyName("position")]
public Ignorable<uint> Position { get; init; }
if only name is set and the other ones arent, they will still get into the Write method and will automatically write out the parent_id: for example which i dont want. can i change this behaviour somehow?
deluvas
deluvas2y ago
var serializeOptions = new JsonSerializerOptions
{
WriteIndented = true,
Converters =
{
new DateTimeOffsetJsonConverter()
}
};

jsonString = JsonSerializer.Serialize(weatherForecast, serializeOptions);
var serializeOptions = new JsonSerializerOptions
{
WriteIndented = true,
Converters =
{
new DateTimeOffsetJsonConverter()
}
};

jsonString = JsonSerializer.Serialize(weatherForecast, serializeOptions);
do you also tell your jsonserializer to use that converter?
Sh1be
Sh1be2y ago
yes
pendramon
pendramon2y ago
Shouldn't you be just running the code in the default case if value.IsDefined? Idk my brain hurts from trying to figure it out 😆
Sh1be
Sh1be2y ago
no because the api wants the ulong and long values to be in string format for whatever reason but thats not the problem
pendramon
pendramon2y ago
No yeah, you are right it is not the problem
Sh1be
Sh1be2y ago
the problem is that the property name gets automatically written out and im not sure how to prevent that
pendramon
pendramon2y ago
Isn't Optional<T> supported by default? Have you tried that?
Sh1be
Sh1be2y ago
this sadly doesn't work for my use case because it works like this: - value set - value is a normal value --> serialize - value null / default --> serialize - value not set --> don't serialize So nullable isnt usable here
pendramon
pendramon2y ago
Okay, so apparently this is not supported by System.Text.Json. In .NET 6 they added json ignore conditions but there is only predefined conditions (null and default value) you can't write your own custom condition as the creation of new properties seems to be handled internally...
Sh1be
Sh1be2y ago
So im out of luck? They didnt add customizable conditions in .net 7 or something?
pendramon
pendramon2y ago
Don't think so I think it may be planned for .NET 8 I'll continue to do some more digging
Sh1be
Sh1be2y ago
Thank you very much for your efforts, I really appreciate it! I couldnt find anything about it when i searched for it. Should I open an issue or something there?
pendramon
pendramon2y ago
There are a few issues about it, but I lost them somewhere :/ It is already known trying to figure out if it is planned or the idea is abandoned now
Sh1be
Sh1be2y ago
I hope its not abandoned
pendramon
pendramon2y ago
GitHub
Developers can customize the JSON serialization contracts of their ...
Background and Motivation Today, System.Text.Json provides two primary mechanisms for customizing serialization on the type level: Customizing the contract via attribute annotations. This is genera...
Sh1be
Sh1be2y ago
The issue is closed and marked as resolved?
pendramon
pendramon2y ago
"unfortunately this scenario is out of scope in this release although we've had long discussion on supporting this - we've decided it's better to support less in this release than supporting everything at once in 2 releases (having said that I'd really wish we could add support for that but at the same time this feature is already large as is and our team has limited resources)." I really hope I'm not miss understanding this, but I do think this issue is for that xD
Sh1be
Sh1be2y ago
I got the same idea as well These JSON contract resolvers The next release will be in .net 8?
pendramon
pendramon2y ago
Honestly, I'm still confused if this would even get more work done in .Net 8 Here is a link for planned things to it but Its so obfuscated I find it hard to read XD
pendramon
pendramon2y ago
GitHub
Planned System.Text.Json contract customization improvements for .N...
Gathering some of the contract customization features we&#39;re planning on working for .NET 8. NB this list is subject to change. Object initialization #73219 #78556 #71944 Contract configurat...
Sh1be
Sh1be2y ago
What am i supposed to do now? Im about 90% through with my migration from newtonsoft to STJ. I dont want to throw everything away now because 1 thing isnt supported
pendramon
pendramon2y ago
:/ I wouldn't know, there must be some way to circumvent this though I'll try a few things
Sh1be
Sh1be2y ago
It seems like that has something to do with this issue Please let me know if you find something, I tried a lot of things and they didnt work STJ exposes a CanConvert method but thats useless for my usecase since it only allows type checking and not value checking
pendramon
pendramon2y ago
How did you register the converter if I may ask? I mean I got something working but the issue is I need to specify all the concrete types I need to use the converter on 🤔
var serializeOptions = new JsonSerializerOptions
{
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault,
WriteIndented = true,
Converters =
{
new OptionalConverter<SomeDto>(),
new OptionalConverter<ulong?>(),
},
};
var serializeOptions = new JsonSerializerOptions
{
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault,
WriteIndented = true,
Converters =
{
new OptionalConverter<SomeDto>(),
new OptionalConverter<ulong?>(),
},
};
I'll figure it out
Sh1be
Sh1be2y ago
Above the property add the attribute [JsonConverter(typeof(Converter)]
pendramon
pendramon2y ago
Eggh, its ugly though
Sh1be
Sh1be2y ago
¯\_(ツ)_/¯ You figured something out?
pendramon
pendramon2y ago
Yes, whether to use JsonIgnoreCondition.WhenWritingDefault option based on the IsDefined property
Sh1be
Sh1be2y ago
Well that wouldnt be what i need. The library is for discord and discord lets you send values that are null or default values to reset a field So this would destroy that functionality I thought about that as well
pendramon
pendramon2y ago
No, basically it works when IsDefined is true Let me double check real quick I may be getting ahead of myself 😄
Sh1be
Sh1be2y ago
How Okay double check The only case where it shouldnt serialize a property is when you havent touched it
pendramon
pendramon2y ago
public override void Write(Utf8JsonWriter writer, Optional<T> value, JsonSerializerOptions options)
{
if (value.HasValue)
{
var serializeOptions = new JsonSerializerOptions
{
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault,
WriteIndented = true,
Converters =
{
new OptionalConverter<SomeDto>(),
new OptionalConverter<ulong>(),
},
};

JsonSerializer.Serialize(writer, value.Value, serializeOptions);
}
else
{
JsonSerializer.Serialize(writer, value.Value);
}
}
public override void Write(Utf8JsonWriter writer, Optional<T> value, JsonSerializerOptions options)
{
if (value.HasValue)
{
var serializeOptions = new JsonSerializerOptions
{
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault,
WriteIndented = true,
Converters =
{
new OptionalConverter<SomeDto>(),
new OptionalConverter<ulong>(),
},
};

JsonSerializer.Serialize(writer, value.Value, serializeOptions);
}
else
{
JsonSerializer.Serialize(writer, value.Value);
}
}
I'm using Optional<T> which basically just has a constructor for value and if you use that constructor it sets HasValue to true I may be just dumb and doing something wrong
Sh1be
Sh1be2y ago
Im not at my pc right now
pendramon
pendramon2y ago
But i tested with unset values, set values to default and set values to null. worked fine. The issue is that I have to pass the concrete type for each type i use in application
Sh1be
Sh1be2y ago
Wait so setting a property to default/null still serializes it? And only doesnt serialize when the property is actually unset?
pendramon
pendramon2y ago
Yes, the property is added to the json when the value is set to default/null or any value in that matter And the property is not added to the json when the property is not set
Sh1be
Sh1be2y ago
That would be amazing if it actually worked
pendramon
pendramon2y ago
- value set - value is a normal value --> serialize - value null / default --> serialize - value not set --> don't serialize fullfills this
Sh1be
Sh1be2y ago
Wait ill get on my pc
pendramon
pendramon2y ago
But I gotta find a way to remove having to register all the types, its bugging me
Sh1be
Sh1be2y ago
no way
pendramon
pendramon2y ago
You see, you have to register a converter for literally all types used inside a Optional<>
Sh1be
Sh1be2y ago
it actually works i didnt think the default attribute worked because the description says it ignores the property when writing null which is insanely misleading
pendramon
pendramon2y ago
Well that is actually not what you want but this is a hacky way to activate it when you need it
Sh1be
Sh1be2y ago
yeah ill have to add the attribute to every property
pendramon
pendramon2y ago
Because you do want null values to be written Nah man I'll figure this out Just wait 😆 Might take me 4 days xD
Sh1be
Sh1be2y ago
you dont have to brother, thank you so much I would have legit never thought about trying it because of the description I feel so happy right now you are a good guy btw i agree with ur about me
pendramon
pendramon2y ago
The issue is I'd probably have to use reflection and I hate having to use reflection in my madge
Sh1be
Sh1be2y ago
who are you
pendramon
pendramon2y ago
A programmer with 0 work experience that struggles to improve himself due to the fact that he has no discipline 😆
Sh1be
Sh1be2y ago
how old are you
pendramon
pendramon2y ago
23 I believe, I don't count my birthdays
Sh1be
Sh1be2y ago
so you have a job in a different field?
pendramon
pendramon2y ago
No, I just don't have the discipline to focus on programming for long periods to actually finish projects and have material to show to employers Like I have been programming as a hobby for many years but I advance so little because I spend so little time coding during the week. But I just don't have the discipline to sit down and code even when I know that, this is what I need to do to improve myself and reach the goals that I clearly want.
Sh1be
Sh1be2y ago
well its good that you see your problem. What I always do is not care about the discipline but just sit down and actually do something, the first part of getting to do something is always the hardest. I wish you luck and maybe you should try that as well
pendramon
pendramon2y ago
I just end up staring at the computer screen blankly and eventually give up to the demons and start when
Sh1be
Sh1be2y ago
You gotta fight that man
pendramon
pendramon2y ago
@Sh1be feast your eyes on this garbage
using System.Reflection;
using System.Text.Json.Serialization;
using System.Text.Json;
using Microsoft.CodeAnalysis;

public class SomeDto
{
public required string Name { get; set; }

public Optional<ulong?> ParentId { get; set; }

public uint Position { get; set; }
}

internal static class OptionalConverterSharedOptions
{
internal static readonly JsonSerializerOptions SerializationOptions = new()
{
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault,
WriteIndented = true,
Converters =
{
new OptionalConverterFactory(),
},
};
}

public class OptionalConverter<T> : JsonConverter<Optional<T>>
{
public override Optional<T> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
throw new NotImplementedException();
}

public override void Write(Utf8JsonWriter writer, Optional<T> value, JsonSerializerOptions options)
{
if (value.HasValue)
{
JsonSerializer.Serialize(writer, value.Value, OptionalConverterSharedOptions.SerializationOptions);
}
else
{
JsonSerializer.Serialize(writer, value.Value);
}
}
}

public class OptionalConverterFactory : JsonConverterFactory
{
public override bool CanConvert(Type typeToConvert)
{
return typeToConvert.IsGenericType && typeToConvert.GetGenericTypeDefinition() == typeof(Optional<>);
}

public override JsonConverter? CreateConverter(Type type, JsonSerializerOptions options)
{
var valueType = type.GetGenericArguments()[0];

return (JsonConverter)Activator.CreateInstance(
typeof(OptionalConverter<>).MakeGenericType(
new Type[] { valueType }),
BindingFlags.Instance | BindingFlags.Public,
null,
null,
null)!;
}
}
using System.Reflection;
using System.Text.Json.Serialization;
using System.Text.Json;
using Microsoft.CodeAnalysis;

public class SomeDto
{
public required string Name { get; set; }

public Optional<ulong?> ParentId { get; set; }

public uint Position { get; set; }
}

internal static class OptionalConverterSharedOptions
{
internal static readonly JsonSerializerOptions SerializationOptions = new()
{
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault,
WriteIndented = true,
Converters =
{
new OptionalConverterFactory(),
},
};
}

public class OptionalConverter<T> : JsonConverter<Optional<T>>
{
public override Optional<T> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
throw new NotImplementedException();
}

public override void Write(Utf8JsonWriter writer, Optional<T> value, JsonSerializerOptions options)
{
if (value.HasValue)
{
JsonSerializer.Serialize(writer, value.Value, OptionalConverterSharedOptions.SerializationOptions);
}
else
{
JsonSerializer.Serialize(writer, value.Value);
}
}
}

public class OptionalConverterFactory : JsonConverterFactory
{
public override bool CanConvert(Type typeToConvert)
{
return typeToConvert.IsGenericType && typeToConvert.GetGenericTypeDefinition() == typeof(Optional<>);
}

public override JsonConverter? CreateConverter(Type type, JsonSerializerOptions options)
{
var valueType = type.GetGenericArguments()[0];

return (JsonConverter)Activator.CreateInstance(
typeof(OptionalConverter<>).MakeGenericType(
new Type[] { valueType }),
BindingFlags.Instance | BindingFlags.Public,
null,
null,
null)!;
}
}
var serializeOptions = new JsonSerializerOptions
{
WriteIndented = true,
Converters =
{
new OptionalConverterFactory(),
},
};

var someDto = new Optional<SomeDto>(new SomeDto
{
Name = "My name",
Position = 20,
});

var jsonString = JsonSerializer.Serialize(someDto, serializeOptions);

Console.WriteLine(jsonString);
// Output:
// {
// "Name": "My name",
// "Position": 20
// }
var serializeOptions = new JsonSerializerOptions
{
WriteIndented = true,
Converters =
{
new OptionalConverterFactory(),
},
};

var someDto = new Optional<SomeDto>(new SomeDto
{
Name = "My name",
Position = 20,
});

var jsonString = JsonSerializer.Serialize(someDto, serializeOptions);

Console.WriteLine(jsonString);
// Output:
// {
// "Name": "My name",
// "Position": 20
// }
reflection 🤮
Sh1be
Sh1be2y ago
a factory??? doesnt look very simple and fun
pendramon
pendramon2y ago
This is how you should do it to to achieve a generic converter based on the msdn docs on how to write a custom converter. There is probably performance issues with it though as with everything else using reflection. I also need to reuse the options instead of creating a new instance all the time...
Sh1be
Sh1be2y ago
so its not really worth it huh?
pendramon
pendramon2y ago
The options instance contains cache of metadata needed for serialization, since I'm now re-using a single options instance for all Optional<> types I think it should be good. It is important to note that the cache size will grow with the amount of different(distinct) types you are using when serializing. For example Optional<int> is one, Optional<string> is two, etc, having multiple of one type shouldn't add to the cache size. Make sure you not re-creating too many JsonSerializerOptions as the serializer undergoes a warm up phase during the first serialization of each type. There are probably more ways of optimizing it but honestly I wouldn't know how to. Here is a quick benchmark on my shitty machine. As you can see it takes ~2.7 seconds with Optional vs ~1.1 seconds without Optional when serializing 100000 entities with same data. Now with the x2.36 slow down you can decide if you find that worth it or not
// * Summary *

BenchmarkDotNet=v0.13.2, OS=Windows 10 (10.0.19044.2364/21H2/November2021Update)
AMD FX(tm)-6300, 1 CPU, 6 logical and 3 physical cores
.NET SDK=7.0.100
[Host] : .NET 7.0.0 (7.0.22.51805), X64 RyuJIT AVX
DefaultJob : .NET 7.0.0 (7.0.22.51805), X64 RyuJIT AVX


| Method | Iterations | Mean | Error | StdDev |
|----------------------------------- |----------- |--------------:|-------------:|-------------:|
| SerializeWithOptionalsBenchmark | 10 | 27.64 μs | 0.551 μs | 1.048 μs |
| SerializeWithoutOptionalsBenchmark | 10 | 11.55 μs | 0.074 μs | 0.057 μs |
| SerializeWithOptionalsBenchmark | 1000 | 2,633.04 μs | 33.238 μs | 29.465 μs |
| SerializeWithoutOptionalsBenchmark | 1000 | 1,141.52 μs | 21.921 μs | 27.723 μs |
| SerializeWithOptionalsBenchmark | 100000 | 268,004.95 μs | 5,341.759 μs | 5,246.321 μs |
| SerializeWithoutOptionalsBenchmark | 100000 | 113,465.49 μs | 1,429.193 μs | 1,336.868 μs |
// * Summary *

BenchmarkDotNet=v0.13.2, OS=Windows 10 (10.0.19044.2364/21H2/November2021Update)
AMD FX(tm)-6300, 1 CPU, 6 logical and 3 physical cores
.NET SDK=7.0.100
[Host] : .NET 7.0.0 (7.0.22.51805), X64 RyuJIT AVX
DefaultJob : .NET 7.0.0 (7.0.22.51805), X64 RyuJIT AVX


| Method | Iterations | Mean | Error | StdDev |
|----------------------------------- |----------- |--------------:|-------------:|-------------:|
| SerializeWithOptionalsBenchmark | 10 | 27.64 μs | 0.551 μs | 1.048 μs |
| SerializeWithoutOptionalsBenchmark | 10 | 11.55 μs | 0.074 μs | 0.057 μs |
| SerializeWithOptionalsBenchmark | 1000 | 2,633.04 μs | 33.238 μs | 29.465 μs |
| SerializeWithoutOptionalsBenchmark | 1000 | 1,141.52 μs | 21.921 μs | 27.723 μs |
| SerializeWithOptionalsBenchmark | 100000 | 268,004.95 μs | 5,341.759 μs | 5,246.321 μs |
| SerializeWithoutOptionalsBenchmark | 100000 | 113,465.49 μs | 1,429.193 μs | 1,336.868 μs |
I should benchmark with Optionals but without the factory but I'm too tired rn, will do it first thing tomorrow cause I'm curious
Wz
Wz2y ago
You have to look into a resolver and not a converter
Wz
Wz2y ago
.NET Blog
Announcing .NET 7 Preview 6
.NET 7 Preview 6 is now available with improvements to type converters, JSON contract customization, System.Formats.Tar API updates, constraints to .NET template authoring, and performance enhancements in the CodeGen area.
Sh1be
Sh1be2y ago
good morning, I fell asleep
Sh1be
Sh1be2y ago
How to ignore properties with System.Text.Json
Learn how to ignore properties when serializing with System.Text.Json in .NET.
Sh1be
Sh1be2y ago
is this a bug? the Optional wrapper was just as a bypass for the problem. If this attribute works though, the whole wrapper can be thrown away and the default converter can be used oh i didnt think those would be available already, but if this magic attribute works the way i need it to, then i dont need it weird that the example msdn talks about is exactly what isnt supposed to be happening
pendramon
pendramon2y ago
Ah damn! How the hell could I miss this...
Sh1be
Sh1be2y ago
how did i miss that as well
pendramon
pendramon2y ago
Its freaking difficult to figure out though... Hold on, how are you going to know whether the value is undefined without the optional wrapper?
Sh1be
Sh1be2y ago
the JsonIgnore condition somehow takes care of it. try it i have no idea how or why
pendramon
pendramon2y ago
what... ok I don't think what you are trying to do now and what you had before in Newtonsoft.Json is the same x)
Sh1be
Sh1be2y ago
it produces the desired result though - value set - value is a normal value --> serialize - value null / default --> serialize - value not set --> don't serialize
pendramon
pendramon2y ago
Newtonsoft.Json's JsonIgnore always ignores the property by default though? 🤔 Do you have a contract resolver or something for Newtonsoft.Json?
Sh1be
Sh1be2y ago
Newtonsoft has these ShouldSerialize methods
pendramon
pendramon2y ago
Well how'd you do those?
pendramon
pendramon2y ago
Yes, I get you but what was your logic inside those methods to tell if the value has been undefined or not?
Sh1be
Sh1be2y ago
thats where the Ignorable / Optional wrapper was used
pendramon
pendramon2y ago
Ah, yes. okay that makes sense
Sh1be
Sh1be2y ago
but now that the attribute somehow tracks whether the value has actually been set, the wrapper isnt needed anymore no idea how it does that
pendramon
pendramon2y ago
Thats why I asked this cuz you said the optional wrapper can be thrown away, which in reality it can't be as you can't then tell if the value is undefined or not Wait what the attribute tracks if it has been set? Where'd you read that?
Sh1be
Sh1be2y ago
yeah i tried it without yesterday and it worked ill fix some errors rn and then show you
pendramon
pendramon2y ago
I think you are wrong on that assumption 🤔
Sh1be
Sh1be2y ago
ugh big projects are annoying you change one thing and everything breaks
pendramon
pendramon2y ago
Thats why you got source control
Sh1be
Sh1be2y ago
@Pendramon okay turns out it didnt work not sure why it worked yesterday im stupid, 2hrs of work for nothing lol
pendramon
pendramon2y ago
I think it worked for null/default value probably and you just didn't check the case of it not being set
Sh1be
Sh1be2y ago
Sh1be
Sh1be2y ago
yeah thats the test, doesnt work without the Ignorable lesson learned @Pendramon@Pendramongo and finish a project
pendramon
pendramon2y ago
No, I'm busy getting distracted on discord stare
Sh1be
Sh1be2y ago
Finish being busy with that and start being busy with coding I wasted 2 hours now u gotta put 2 hours to good use
pendramon
pendramon2y ago
I wasted 4 hours tryna cast Optional<of any type> to Optional<object> cuz I'm a when
Sh1be
Sh1be2y ago
Lmao
pendramon
pendramon2y ago
Don't think its possible x)
Sh1be
Sh1be2y ago
Try harder Surprised you put in the 4 hours effort into it though
pendramon
pendramon2y ago
I get bored after working on the same project for some time, starting new projects that I'll never finish is fun when
Sh1be
Sh1be2y ago
Lmao I hope we will finish this project Else many hours will have been for nothing
pendramon
pendramon2y ago
I mean technically we achieved our goal But if its performant enough is another when
Sh1be
Sh1be2y ago
Its certainly faster than newtonsoft The barebones implementation i have The one you have is slower ofc
pendramon
pendramon2y ago
Why you say that? did you benchmark it? ok was bout to say I'd be surprised
Sh1be
Sh1be2y ago
No i didnt benchmark it But newtonsoft is still insanely slower I read a benchmark once
pendramon
pendramon2y ago
It is slower indeed Just benchmarked it and the factory I wrote above actually improves the speed by 0.27% instead of the no factory version But implementing conditional serialization could end up being even faster 🤔 IF it actually can be used for this use case
Sh1be
Sh1be2y ago
this contract resolver could be worth a look perhaps that makes it faster and clearer, as right now the WhenWritingDefault attribute is kind of a magic box
pendramon
pendramon2y ago
When I think about it I actually don't think it will be faster WhenWritingDefault is basically what we needed the whole time The only thing that we just needed to do is check if it HasValue before serializing Because every unassigned variable is set to its default
Sh1be
Sh1be2y ago
Yeah but the question arises why does it still pass if its set to be null/default by the user That goes against its description and example
pendramon
pendramon2y ago
Ohhh I see where you are confused Well crap... found a bug 😄
Sh1be
Sh1be2y ago
hm?
pendramon
pendramon2y ago
I think it never even worked in the first place x) I don't think I broke anything but I can't reproduce the correct results
Sh1be
Sh1be2y ago
you should start a new project /// <summary> /// If the value is the default, the property is ignored during serialization. /// This is applied to both reference and value-type properties and fields. /// </summary> WhenWritingDefault = 2, now this is a better explanation I understand why this works now
pendramon
pendramon2y ago
But exactly that is the problem It does exactly that. hence why it DOESN'T work - value set - value is a normal value --> serialize - value null / default --> serialize - value not set --> don't serialize Does not full fill this ^ My tests were just bad...
Sh1be
Sh1be2y ago
it works with my wrapper class because of the IsDefined property that gets set to true when the value is being set so it isnt in default state anymore even if the value is default
pendramon
pendramon2y ago
The only way I'm able to construct an instance of this Optional class is when I pass a value inside the constructor. Hence should work Are you sure you are not just testing it bad like I was? x) Try adding a default value and see if it is written To a non optional property
Sh1be
Sh1be2y ago
look here
pendramon
pendramon2y ago
This is now more like Required instead of Optional
Sh1be
Sh1be2y ago
oh i dont have a non optional property sorry
Accord
Accord2y 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
More Posts