* Fix STJ source gen support for System.BinaryData.
* remove redundant sealed keyword from converter overrides
* Generate compatibility suppressions
* Add comment to compatibility suppressions
namespace System
{
- [System.Text.Json.Serialization.JsonConverter(typeof(BinaryDataConverter))]
+ [System.Text.Json.Serialization.JsonConverterAttribute(typeof(System.Text.Json.Serialization.BinaryDataJsonConverter))]
public partial class BinaryData
{
public BinaryData(byte[] data) { }
public BinaryData(System.ReadOnlyMemory<byte> data) { }
public BinaryData(string data) { }
public static System.BinaryData Empty { get { throw null; } }
+ public bool IsEmpty { get { throw null; } }
+ public int Length { get { throw null; } }
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; }
public static System.BinaryData FromBytes(byte[] data) { throw null; }
public static System.BinaryData FromString(string data) { throw null; }
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
public override int GetHashCode() { throw null; }
- public bool IsEmpty { get { throw null; } }
- public int Length { get { throw null; } }
public static implicit operator System.ReadOnlyMemory<byte> (System.BinaryData? data) { throw null; }
public static implicit operator System.ReadOnlySpan<byte> (System.BinaryData? data) { throw null; }
public byte[] ToArray() { throw null; }
public System.IO.Stream ToStream() { throw null; }
public override string ToString() { throw null; }
}
-
- internal sealed class BinaryDataConverter : System.Text.Json.Serialization.JsonConverter<BinaryData>
+}
+namespace System.Text.Json.Serialization
+{
+ public sealed partial class BinaryDataJsonConverter : System.Text.Json.Serialization.JsonConverter<System.BinaryData>
{
- public sealed override BinaryData? Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) { throw null; }
- public sealed override void Write(System.Text.Json.Utf8JsonWriter writer, BinaryData value, System.Text.Json.JsonSerializerOptions options) { }
+ public BinaryDataJsonConverter() { }
+ public override System.BinaryData? Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) { throw null; }
+ public override void Write(System.Text.Json.Utf8JsonWriter writer, System.BinaryData value, System.Text.Json.JsonSerializerOptions options) { }
}
}
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- https://learn.microsoft.com/en-us/dotnet/fundamentals/package-validation/diagnostic-ids -->
+<Suppressions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+ <!-- Move JsonConverterAttribute argument from internal to a public converter type in a new namespace -->
+ <Suppression>
+ <DiagnosticId>CP0015</DiagnosticId>
+ <Target>T:System.BinaryData:[T:System.Text.Json.Serialization.JsonConverterAttribute]</Target>
+ <Left>lib/net462/System.Memory.Data.dll</Left>
+ <Right>lib/net462/System.Memory.Data.dll</Right>
+ <IsBaselineSuppression>true</IsBaselineSuppression>
+ </Suppression>
+ <Suppression>
+ <DiagnosticId>CP0015</DiagnosticId>
+ <Target>T:System.BinaryData:[T:System.Text.Json.Serialization.JsonConverterAttribute]</Target>
+ <Left>lib/net6.0/System.Memory.Data.dll</Left>
+ <Right>lib/net6.0/System.Memory.Data.dll</Right>
+ <IsBaselineSuppression>true</IsBaselineSuppression>
+ </Suppression>
+ <Suppression>
+ <DiagnosticId>CP0015</DiagnosticId>
+ <Target>T:System.BinaryData:[T:System.Text.Json.Serialization.JsonConverterAttribute]</Target>
+ <Left>lib/net7.0/System.Memory.Data.dll</Left>
+ <Right>lib/net7.0/System.Memory.Data.dll</Right>
+ <IsBaselineSuppression>true</IsBaselineSuppression>
+ </Suppression>
+ <Suppression>
+ <DiagnosticId>CP0015</DiagnosticId>
+ <Target>T:System.BinaryData:[T:System.Text.Json.Serialization.JsonConverterAttribute]</Target>
+ <Left>lib/netstandard2.0/System.Memory.Data.dll</Left>
+ <Right>lib/netstandard2.0/System.Memory.Data.dll</Right>
+ <IsBaselineSuppression>true</IsBaselineSuppression>
+ </Suppression>
+</Suppressions>
\ No newline at end of file
/// <summary>
/// A lightweight abstraction for a payload of bytes that supports converting between string, stream, JSON, and bytes.
/// </summary>
- [JsonConverter(typeof(BinaryDataConverter))]
+ [JsonConverter(typeof(BinaryDataJsonConverter))]
public class BinaryData
{
private const string JsonSerializerRequiresDynamicCode = "JSON serialization and deserialization might require types that cannot be statically analyzed and might need runtime code generation.";
[RequiresDynamicCode(JsonSerializerRequiresDynamicCode)]
[RequiresUnreferencedCode(JsonSerializerRequiresUnreferencedCode)]
public T? ToObjectFromJson<T>(JsonSerializerOptions? options = default)
- {
- ReadOnlySpan<byte> span = _bytes.Span;
-
- // Check for the UTF-8 byte order mark (BOM) EF BB BF
- if (span.Length > 2 && span[0] == 0xEF && span[1] == 0xBB && span[2] == 0xBF)
- span = span.Slice(3);
-
- return JsonSerializer.Deserialize<T>(span, options);
- }
+ => JsonSerializer.Deserialize<T>(GetBytesWithTrimmedBom(), options);
/// <summary>
/// Converts the <see cref="BinaryData"/> to the specified type using
/// <param name="jsonTypeInfo">The <see cref="JsonTypeInfo"/> to use when serializing to JSON.</param>
/// <returns>The data converted to the specified type.</returns>
public T? ToObjectFromJson<T>(JsonTypeInfo<T> jsonTypeInfo)
- => JsonSerializer.Deserialize<T>(_bytes.Span, jsonTypeInfo);
+ => JsonSerializer.Deserialize(GetBytesWithTrimmedBom(), jsonTypeInfo);
+
+ private ReadOnlySpan<byte> GetBytesWithTrimmedBom()
+ {
+ ReadOnlySpan<byte> span = _bytes.Span;
+
+ // Check for the UTF-8 byte order mark (BOM) EF BB BF
+ if (span.Length > 2 && span[0] == 0xEF && span[1] == 0xBB && span[2] == 0xBF)
+ span = span.Slice(3);
+
+ return span;
+ }
/// <summary>
/// Defines an implicit conversion from a <see cref="BinaryData" /> to a <see cref="ReadOnlyMemory{Byte}"/>.
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-using System.Text.Json;
-using System.Text.Json.Serialization;
-
-namespace System
+namespace System.Text.Json.Serialization
{
- internal sealed class BinaryDataConverter : JsonConverter<BinaryData>
+ /// <summary>
+ /// Serializes <see cref="BinaryData"/> instances as Base64 JSON strings.
+ /// </summary>
+ public sealed class BinaryDataJsonConverter : JsonConverter<BinaryData>
{
- public sealed override BinaryData? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+ /// <inheritdoc/>
+ public override BinaryData? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return BinaryData.FromBytes(reader.GetBytesFromBase64());
}
- public sealed override void Write(Utf8JsonWriter writer, BinaryData value, JsonSerializerOptions options)
+ /// <inheritdoc/>
+ public override void Write(Utf8JsonWriter writer, BinaryData value, JsonSerializerOptions options)
{
writer.WriteBase64StringValue(value.ToMemory().Span);
}
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
data = BinaryData.FromObjectAsJson<TestModel>(null);
Assert.Null(data.ToObjectFromJson<TestModel>());
- data = BinaryData.FromObjectAsJson<TestModel>(null, TestModelJsonContext.Default.TestModel as JsonTypeInfo<TestModel>);
+ data = BinaryData.FromObjectAsJson<TestModel>(null, TestModelJsonContext.Default.TestModel);
Assert.Null(data.ToObjectFromJson<TestModel>(TestModelJsonContext.Default.TestModel));
}
ex = await Assert.ThrowsAsync<ArgumentNullException>(() => BinaryData.FromStreamAsync(null));
Assert.Contains("stream", ex.Message);
-
}
[Fact]
Assert.Equal(payload.A, model.A);
Assert.Equal(payload.B, model.B);
Assert.Equal(payload.C, model.C);
+
+ var typeInfo = (JsonTypeInfo<TestModel>)JsonSerializerOptions.Default.GetTypeInfo(typeof(TestModel));
+ model = data.ToObjectFromJson<TestModel>(typeInfo);
+ Assert.Equal(payload.A, model.A);
+ Assert.Equal(payload.B, model.B);
+ Assert.Equal(payload.C, model.C);
}
[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBuiltWithAggressiveTrimming))]
Assert.False(data.IsEmpty);
}
- [Fact]
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBuiltWithAggressiveTrimming))]
public void IsBinaryDataMemberPropertySerialized()
{
var data = new BinaryData("A test value");
Assert.Equal(jsonTestModel, serializedTestModel);
}
- [Fact]
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBuiltWithAggressiveTrimming))]
public void IsBinaryDataMemberPropertyDeserialized()
{
var data = new BinaryData("A test value");
Assert.Equal(data.ToString(), deserializedModel.A.ToString());
}
+ [Fact]
+ public void IsBinaryDataMemberPropertySerialized_SourceGen()
+ {
+ var data = new BinaryData("A test value");
+ var dataBase64 = Convert.ToBase64String(data.ToArray());
+ var jsonTestModel = $"{{\"A\":\"{dataBase64}\"}}";
+ TestModelWithBinaryDataProperty testModel = new TestModelWithBinaryDataProperty { A = data };
+
+ var serializedTestModel = JsonSerializer.Serialize(testModel, TestModelWithBinaryDataPropertyContext.Default.TestModelWithBinaryDataProperty);
+
+ Assert.Equal(jsonTestModel, serializedTestModel);
+ }
+
+ [Fact]
+ public void IsBinaryDataMemberPropertyDeserialized_SourceGen()
+ {
+ var data = new BinaryData("A test value");
+ var dataBase64 = Convert.ToBase64String(data.ToArray());
+ var jsonTestModel = $"{{\"A\":\"{dataBase64}\"}}";
+
+ TestModelWithBinaryDataProperty deserializedModel = JsonSerializer.Deserialize<TestModelWithBinaryDataProperty>(jsonTestModel, TestModelWithBinaryDataPropertyContext.Default.TestModelWithBinaryDataProperty);
+
+ Assert.Equal(data.ToString(), deserializedModel.A.ToString());
+ }
+
internal class TestModel
{
public string A { get; set; }
{
public BinaryData A { get; set; }
}
+
+ [JsonSerializable(typeof(TestModelWithBinaryDataProperty))]
+ internal partial class TestModelWithBinaryDataPropertyContext : JsonSerializerContext
+ { }
}
}
<PropertyGroup>
<TargetFrameworks>$(NetCoreAppCurrent);$(NetFrameworkMinimum)</TargetFrameworks>
- <JsonSerializerIsReflectionEnabledByDefault>true</JsonSerializerIsReflectionEnabledByDefault>
</PropertyGroup>
<ItemGroup>