macross-software / core Goto Github PK
View Code? Open in Web Editor NEWCore repository contains the primary open source libraries released by Macross Software for .NET Core.
License: MIT License
Core repository contains the primary open source libraries released by Macross Software for .NET Core.
License: MIT License
This should work
[JsonConverter(typeof(JsonStringEnumMemberConverter))]
enum A
{
[JsonPropertyName("abc")]
X,
}
Macross.Logging.Abstractions v2.0 contains an outdated reference to System.Text.Encodings.Web dll
please update it to v5.0.1
Hi,
thanks for JsonStringEnumConverter, it's what I was looking for. Unfortunately, the converter can't be used when System.Text.Json.Serialization.JsonStringEnumConverter is registered globally.
Here is a sample repository.
There are two projects and a shared library with enums. The first project is called "Enums" and there is defined global System.Text.Json.Serialization.JsonStringEnumConverter. So, with that one can't use enum values as they are defined with the EnumMember attribute. The second project is called "EnumMembers" and there is no global enum converter registered, that is working as expected, but for enums without JsonConverter one must use numbers instead of a string.
We serialize and deserialize enums as strings, but sometimes (OpenID connect client registration) we need to follow the standard and use defined naming convention, so EnumMember attributes are in place and we don't want every enum to decorate with JsonConverter attribute.
Is there a way out?
In your Json extensions code, if I format CultureInfo's DateTimeFormat, the property MinSupportedDateTime comes out like this:
JavascriptSerializer/DateFormatHandling.Microsoft = "MinSupportedDateTime":"/Date(-62135596800000)/"
But with your code, it seems to come out like "MinSupportedDateTime":"/Date(-62135596800000)/" (missing the \ before /). Will that still work as intended?
I noticed that your dependency on System.Text.Json version 4.7.0 has a security issue.
Are there any plans to upgrade this to a secure version? I would love to use this library but that is currently an issue for us.
Here's what my scanner found along with some information on remediation steps. I think it's as simple as bumping up System.Text.Json to 4.7.2+
Detailed paths
Introduced through: project@undefined › [email protected] › [email protected] › [email protected]
Overview
Affected versions of this package are vulnerable to Remote Code Execution (RCE) due to how text encoding is performed.
Remediation
Upgrade System.Text.Encodings.Web to version 4.5.1, 4.7.2, 5.0.1 or higher.
The FileLogger
converts the LogEvent into a LoggerJsonMessage
:
But be careful when the extracted properties are complex objects that can be mutable (ex disposed or returned to object pool after being logged). Then the output might not be like you expect, when the async-writer finally starts converting to the actual json-output.
I get this error when trying to parse a json with the value "/Date(-62135575200000-0600)/" to a datetime.
Think it should just be private readonly
:
If having multiple FileLoggerProvider
-instances then it will generate unexpected output. Ex. if having multiple Host-instances, or if one day adding support for multiple files within the same host.
Hi! I see that there were several beta releases for Macross.Json.Extensions 2.1.0, but never a production release (at least not on NuGet Gallery). Was that an oversight or did you decide not to release 2.1.0 before proceeding into beta on 2.2.0?
Problem reference
dotnet/runtime#73124
Fix
dotnet/runtime#79311 (comment)
dotnet/runtime#87224
When JsonStringEnumMemberConverter is used to convert enum with JsonNamingPolicy, converted enum values aren't converted based on given naming policy.
When working with [Flags]
enums, these are often represented as an array of strings in JSON.
It would be nice to have this functionality too in the JsonStringEnumMemberConverter
.
It should check if the value is a string
or a number
and proceed as before, but also introduce support if the value is an array
.
The unknown enum value is not handled properly and returns 500 HTTP status code instead of 400 HTTP status code.
Currently it seems that the library deserializes enum values without taking case sensitivity into an account, so e.g. a value of "hELLo"
successfully deserializes into the enum value Hello
. Is there a way to force an exception if the casing isn't exactly as specified in the [EnumMember]
attribute?
Thank you for this project, it has been helpful to me in accepting non-standard string values for my enums.
I have a need in the deserialization of an Enum from a string to be able to accept different values/aliases that tie back to the same Enum value. Additionally, if that enum value was deserialized with an alias, I'd like it to be serialized using the default value, not an alias value.
As a made up (probably bad) example pretend I have a Color
enum:
public enum Color
{
Red,
Green,
Blue,
}
And I'd like to accept both the color name or the hex value:
{
"color": "FF0000",
"highlightColor": "Blue"
}
And then if that object which was originally deserialized was then serialized I'd like it to consistently serialize to the default value names like the following:
{
"color": "Red",
"highlightColor": "Blue"
}
Originally I just added a new Enum value, set it equal to the default value and that works for deserialization and comparing the value to Color.Red
in code. But doesn't work when re-serializing the value back out. It look like doing it this way always writes out the last defined value which in this case is the alias value instead of the desired default value.
public enum Color
{
Red,
[EnumMember(Value = "FF0000")]
RedHex = Red,
Green,
[EnumMember(Value = "00FF00")]
GreenHex = Green,
Blue,
[EnumMember(Value = "0000FF")]
BlueHex = Blue,
}
Is there anything in your Converter that could help with this, or is there anything I'm missing?
Hi,
I've tried the combination of
`[JsonStringEnumMemberConverterOptions(deserializationFailureFallbackValue: MyEnum.Unknown)]
[JsonConverter(typeof(JsonStringEnumMemberConverter))]
public enum MyEnum
{
Unknown = 0,
[EnumMember(Value = "value1")]
ValidValue = 1
}`
When I use the following custom policy name :
public void ConfigureServices(IServiceCollection services) { services.AddControllers() .AddJsonOptions(options => { options.JsonSerializerOptions.Converters.Add(new JsonStringEnumMemberConverter(new UpperSnakeCaseNamingPolicy(), false)); options.JsonSerializerOptions.WriteIndented = true; });
Issues observed:
Am I missing something in my implementation?
Since upgrading Macross, and removing JsonTimeSpanConverter I noticed my API can no longer bind "0" to a TimeSpan. Same with values like "1:01"
Is there a way to restore this functionality?
NLog opens and closes the file for every file-write by default for compatibility reasons. So instead of doing this:
core/ClassLibraries/Macross.Logging.Files/Benchmarks/NLogProvider.cs
Lines 30 to 34 in 74f37d6
Then do like this:
Target Target = new FileTarget("File")
{
FileName = $"{LogFileDirectoryPath}nlog -${{shortdate}}.log",
Layout = Layout,
KeepFileOpen = true, // Serilog Default, but not for NLog
ConcurrentWrites = false, // Same as Serilog Shared
Autoflush = true, // Same as Serilog Buffered
};
If you want to increase performance even further, then you can enable NLog AsyncWrapper (Enables batch witing of LogEvents using background-timer-thread. Gives much better performance when multiple threads are concurrently logging):
Target = new AsyncTargetWrapper("FileAsync", Target) { OverflowAction = AsyncTargetWrapperOverflowAction.Grow };
I cannot use JsonStringEnumMemberConverter
with [FromQuery]
in my .NET 6 AspNetCore controllers to deserialize enum values matching a specific EnumMember
. It seems the binder fails (with and without JsonStringEnumMemberConverter)
See my next comment for a repo to reproduce and the different approaches taken.
It would be nice to have an option for ignoring failures to parse enum values, and setting the member to the default value or the 0 value instead.
Example use case:
I am parsing data from an external service and one of the values is a string value with a limited set of values. I use an enum in conjunction with JsonStringEnumMemberConverter in order to keep my code clean and ensure I don't typo any of those strings the 100s of times I am comparing them throughout the code.
One day the external service adds in a new string to the list of strings they use in this field. Due to what I am doing I don't care about data with this new value. As things are right now the JSON parsing would fail.
If I could indicate to JsonStringEnumMemberConverter I wanted it to ignore these errors and return a default/0 value instead, I could reserve enum value 0 to mean "invalid" and check for this value to determine if the value was not parsed (or potentially use a nullable enum and check for null) and ignore the specific object. In other scenarios I could try to recover or use partial data after detecting this case.
Workaround for now I will probably go with is for me to pull in the source code of JsonStringEnumMemberConverter directly and replace the throw statements with return statements casting 0 to the proper type.
When trying to populate a nullable DateTime property from a JSON string with a null value an exception is thrown when employing JsonMicrosoftDateTimeConverter
.
C#
[JsonConverter(typeof(JsonMicrosoftDateTimeConverter))]
public DateTime? PaymentDueDate { get; set; }
JSON:
...
"PaymentDueDate": null,
...
Exception:
Message:
System.Text.Json.JsonException : The JSON value could not be converted to System.Nullable 1[System.DateTime]. Path: $.PaymentDueDate | LineNumber: 75 | BytePositionInLine: 28.
Stack Trace:
JsonDateTimeConverter 1.ReadDateTime(Utf8JsonReader& reader)
JsonNullableDateTimeConverter.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options)
JsonConverter 1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
JsonPropertyInfo 1.ReadJsonAndSetMember(Object obj, ReadStack& state, Utf8JsonReader& reader)
ObjectDefaultConverter 1.ReadPropertyValue(Object obj, ReadStack& state, Utf8JsonReader& reader, JsonPropertyInfo jsonPropertyInfo, Boolean useExtensionProperty)
ObjectDefaultConverter 1.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
JsonConverter 1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
JsonConverter 1.ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
JsonSerializer.ReadCore[TValue](JsonConverter jsonConverter, Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
JsonSerializer.ReadCore[TValue](Utf8JsonReader& reader, Type returnType, JsonSerializerOptions options)
JsonSerializer.Deserialize[TValue](String json, Type returnType, JsonSerializerOptions options)
JsonSerializer.Deserialize[TValue](String json, JsonSerializerOptions options)
JsonTests.AdHocDeserialiseTest() line 128
--- End of stack trace from previous location where exception was thrown ---
When using an enum with JsonStringEnumMemberConverter
as a dictionary key it'll fail:
The type 'App.MyEnum' is not a supported dictionary key using converter of type 'System.Text.Json.Serialization.JsonStringEnumMemberConverter+EnumMemberConverter`1[App.MyEnum]'.
The enum & class to reproduce this:
[JsonConverter(typeof(JsonStringEnumMemberConverter))]
public enum MyEnum
{
[EnumMember(Value = "one")]
One = 1,
[EnumMember(Value = "two")]
Two = 2,
}
public class MyModel
{
[JsonPropertyName("stuff")]
public IDictionary<MyEnum, string> Stuff { get; set; }
}
ReadAsPropertyName()
& WriteAsPropertyName()
need to be added to the converter to fix this: dotnet/runtime#46520 (comment)
If I declare an enum for use with my data contract, it does not get applied unless the containing class member also specifies to use that converter.
Further more, this does not work if you have an array of your enum.
contracts.api.v1.role
[JsonConverter(typeof(Macross.Json.Extensions.JsonStringEnumMemberConverter))] //doesn't work unless specified on each child property of the class that uses it
public enum Role
{
[EnumMember(Value = "Admin")]
Admin = 1,
[EnumMember(Value = "User")]
User = 2,
}
contracts.api.v1.user
public class User
{
public string Username { get; set; } = string.Empty;
[JsonConverter(typeof(Macross.Json.Extensions.JsonStringEnumMemberConverter))]//exception: JsonStringEnumMemberConverter is not compatible with type Role[], does not deserialize properly without this declaration
public Role[] Roles { get; set; } = new Role[0];
}
The regex doesn't seem to be working for strings like:
/Date(1582624800000+0800)/
None of the unit tests seem to test dates with a + or - in them either.
cheers!
In case of using a custom converter policy for example:
options.Converters.Add(new JsonStringEnumMemberConverter(new UpperSnakeCaseNamingPolicy(), false));
class public enum Days
{
SundayDay,
MondayDay,
FridayDay
}
In POST action , when trying to deserialize "SUNDAY_DAY " the input can be :
We might want to support backward compatibility to deserialize same enum type option to itself.
So in POST action , when trying to deserialize "SundayDay " to -> Days.SundayDay it will work.
Adding this line of code, will accomplish that:
_TransformedToRaw[typedValue.ToString()] = new EnumInfo(name, typedValue, rawValue);
Please consider adding this capability to the code.
Thanks!
Settings for controller:
builder.Services.AddControllers().AddJsonOptions(options =>
{ options.JsonSerializerOptions.Converters
.Add(new JsonStringEnumMemberConverter());
});
Enums:
using System;
using System.Runtime.Serialization;
using System.Text.Json.Serialization;
namespace OCPIServer.Application.Ocpi.Contracts.Enums.Versioning;
//I tried with and without attributes
//[JsonStringEnumMemberConverterOptions(deserializationFailureFallbackValue: OcpiVersion.Unknown)]
//[JsonConverter(typeof(JsonStringEnumMemberConverter))]
public enum OcpiVersion
{
[EnumMember(Value = "unknown")]
Unknown = 0,
[EnumMember(Value = "2.0")]
v2_0 = 200,
[EnumMember(Value = "2.1")]
v2_1 = 210
}
Controller(endpoint):
[HttpGet("versions/{version}")]
public GetVersionModel GetVersions(OcpiVersion version)
{
return _ocpiVersionsService.GetVersion(version);
}
Everything works if you set 210 or v2_1_0 in the request. But I need the value (2.1.0) to be specified in the request. Like this
https://localhost:7059/.../versions/2.1.0.
But that doesn't work. Deserialization does not occur. I get error 400 "The value '2.1.0' is not valid."
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.