mirror of https://github.com/Squidex/squidex.git
Browse Source
* Started conversion. * Made progress. * More fixes. * Fix tests * Fix null writing. * More fixes * Fix rule formatting.pull/908/head
committed by
GitHub
190 changed files with 2819 additions and 2088 deletions
@ -1,105 +0,0 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using MongoDB.Bson; |
|||
using MongoDB.Bson.IO; |
|||
using NewtonsoftJsonReader = Newtonsoft.Json.JsonReader; |
|||
using NewtonsoftJsonToken = Newtonsoft.Json.JsonToken; |
|||
|
|||
namespace Squidex.Infrastructure.MongoDb |
|||
{ |
|||
public sealed class BsonJsonReader : NewtonsoftJsonReader |
|||
{ |
|||
private readonly IBsonReader bsonReader; |
|||
|
|||
public BsonJsonReader(IBsonReader bsonReader) |
|||
{ |
|||
Guard.NotNull(bsonReader); |
|||
|
|||
this.bsonReader = bsonReader; |
|||
} |
|||
|
|||
public override bool Read() |
|||
{ |
|||
if (bsonReader.State is BsonReaderState.Initial or BsonReaderState.ScopeDocument or BsonReaderState.Type) |
|||
{ |
|||
bsonReader.ReadBsonType(); |
|||
} |
|||
|
|||
if (bsonReader.State == BsonReaderState.Name) |
|||
{ |
|||
SetToken(NewtonsoftJsonToken.PropertyName, bsonReader.ReadName().UnescapeBson()); |
|||
} |
|||
else if (bsonReader.State == BsonReaderState.Value) |
|||
{ |
|||
switch (bsonReader.CurrentBsonType) |
|||
{ |
|||
case BsonType.Document: |
|||
SetToken(NewtonsoftJsonToken.StartObject); |
|||
bsonReader.ReadStartDocument(); |
|||
break; |
|||
case BsonType.Array: |
|||
SetToken(NewtonsoftJsonToken.StartArray); |
|||
bsonReader.ReadStartArray(); |
|||
break; |
|||
case BsonType.Undefined: |
|||
SetToken(NewtonsoftJsonToken.Undefined); |
|||
bsonReader.ReadUndefined(); |
|||
break; |
|||
case BsonType.Null: |
|||
SetToken(NewtonsoftJsonToken.Null); |
|||
bsonReader.ReadNull(); |
|||
break; |
|||
case BsonType.String: |
|||
SetToken(NewtonsoftJsonToken.String, bsonReader.ReadString()); |
|||
break; |
|||
case BsonType.Binary: |
|||
SetToken(NewtonsoftJsonToken.Bytes, bsonReader.ReadBinaryData().Bytes); |
|||
break; |
|||
case BsonType.Boolean: |
|||
SetToken(NewtonsoftJsonToken.Boolean, bsonReader.ReadBoolean()); |
|||
break; |
|||
case BsonType.DateTime: |
|||
SetToken(NewtonsoftJsonToken.Date, bsonReader.ReadDateTime()); |
|||
break; |
|||
case BsonType.Int32: |
|||
SetToken(NewtonsoftJsonToken.Integer, bsonReader.ReadInt32()); |
|||
break; |
|||
case BsonType.Int64: |
|||
SetToken(NewtonsoftJsonToken.Integer, bsonReader.ReadInt64()); |
|||
break; |
|||
case BsonType.Double: |
|||
SetToken(NewtonsoftJsonToken.Float, bsonReader.ReadDouble()); |
|||
break; |
|||
case BsonType.Decimal128: |
|||
SetToken(NewtonsoftJsonToken.Float, Decimal128.ToDouble(bsonReader.ReadDecimal128())); |
|||
break; |
|||
default: |
|||
ThrowHelper.NotSupportedException(); |
|||
break; |
|||
} |
|||
} |
|||
else if (bsonReader.State == BsonReaderState.EndOfDocument) |
|||
{ |
|||
SetToken(NewtonsoftJsonToken.EndObject); |
|||
bsonReader.ReadEndDocument(); |
|||
} |
|||
else if (bsonReader.State == BsonReaderState.EndOfArray) |
|||
{ |
|||
SetToken(NewtonsoftJsonToken.EndArray); |
|||
bsonReader.ReadEndArray(); |
|||
} |
|||
|
|||
if (bsonReader.State == BsonReaderState.Initial) |
|||
{ |
|||
return true; |
|||
} |
|||
|
|||
return !bsonReader.IsAtEndOfFile(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,91 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using MongoDB.Bson; |
|||
using MongoDB.Bson.Serialization; |
|||
using MongoDB.Bson.Serialization.Serializers; |
|||
using Squidex.Infrastructure.Json.Objects; |
|||
|
|||
namespace Squidex.Infrastructure.MongoDb |
|||
{ |
|||
public sealed class BsonJsonValueSerializer : SerializerBase<JsonValue> |
|||
{ |
|||
public static void Register() |
|||
{ |
|||
try |
|||
{ |
|||
BsonSerializer.RegisterSerializer(new BsonJsonValueSerializer()); |
|||
} |
|||
catch (BsonSerializationException) |
|||
{ |
|||
return; |
|||
} |
|||
} |
|||
|
|||
public override JsonValue Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) |
|||
{ |
|||
var reader = context.Reader; |
|||
|
|||
switch (reader.CurrentBsonType) |
|||
{ |
|||
case BsonType.Undefined: |
|||
reader.ReadUndefined(); |
|||
return JsonValue.Null; |
|||
case BsonType.Null: |
|||
reader.ReadNull(); |
|||
return JsonValue.Null; |
|||
case BsonType.Boolean: |
|||
return reader.ReadBoolean(); |
|||
case BsonType.Double: |
|||
return reader.ReadDouble(); |
|||
case BsonType.Int32: |
|||
return reader.ReadInt32(); |
|||
case BsonType.Int64: |
|||
return reader.ReadInt64(); |
|||
case BsonType.String: |
|||
return reader.ReadString(); |
|||
case BsonType.Array: |
|||
return BsonSerializer.Deserialize<JsonArray>(reader); |
|||
case BsonType.Document: |
|||
return BsonSerializer.Deserialize<JsonObject>(reader); |
|||
default: |
|||
ThrowHelper.NotSupportedException("Unsupported Representation."); |
|||
return default!; |
|||
} |
|||
} |
|||
|
|||
public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, JsonValue value) |
|||
{ |
|||
var writer = context.Writer; |
|||
|
|||
switch (value.Value) |
|||
{ |
|||
case null: |
|||
writer.WriteNull(); |
|||
break; |
|||
case bool b: |
|||
writer.WriteBoolean(b); |
|||
break; |
|||
case string s: |
|||
writer.WriteString(s); |
|||
break; |
|||
case double n: |
|||
writer.WriteDouble(n); |
|||
break; |
|||
case JsonArray a: |
|||
BsonSerializer.Serialize(writer, a); |
|||
break; |
|||
case JsonObject o: |
|||
BsonSerializer.Serialize(writer, o); |
|||
break; |
|||
default: |
|||
ThrowHelper.NotSupportedException(); |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,190 +0,0 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using MongoDB.Bson.IO; |
|||
using NewtonsoftJsonWriter = Newtonsoft.Json.JsonWriter; |
|||
|
|||
namespace Squidex.Infrastructure.MongoDb |
|||
{ |
|||
public sealed class BsonJsonWriter : NewtonsoftJsonWriter |
|||
{ |
|||
private readonly IBsonWriter bsonWriter; |
|||
|
|||
public BsonJsonWriter(IBsonWriter bsonWriter) |
|||
{ |
|||
Guard.NotNull(bsonWriter); |
|||
|
|||
this.bsonWriter = bsonWriter; |
|||
} |
|||
|
|||
public override void WritePropertyName(string name) |
|||
{ |
|||
bsonWriter.WriteName(name.EscapeJson()); |
|||
} |
|||
|
|||
public override void WritePropertyName(string name, bool escape) |
|||
{ |
|||
bsonWriter.WriteName(name.EscapeJson()); |
|||
} |
|||
|
|||
public override void WriteStartArray() |
|||
{ |
|||
bsonWriter.WriteStartArray(); |
|||
} |
|||
|
|||
public override void WriteEndArray() |
|||
{ |
|||
bsonWriter.WriteEndArray(); |
|||
} |
|||
|
|||
public override void WriteStartObject() |
|||
{ |
|||
bsonWriter.WriteStartDocument(); |
|||
} |
|||
|
|||
public override void WriteEndObject() |
|||
{ |
|||
bsonWriter.WriteEndDocument(); |
|||
} |
|||
|
|||
public override void WriteNull() |
|||
{ |
|||
bsonWriter.WriteNull(); |
|||
} |
|||
|
|||
public override void WriteUndefined() |
|||
{ |
|||
bsonWriter.WriteUndefined(); |
|||
} |
|||
|
|||
public override void WriteValue(string? value) |
|||
{ |
|||
if (value == null) |
|||
{ |
|||
bsonWriter.WriteNull(); |
|||
} |
|||
else |
|||
{ |
|||
bsonWriter.WriteString(value); |
|||
} |
|||
} |
|||
|
|||
public override void WriteValue(int value) |
|||
{ |
|||
bsonWriter.WriteInt32(value); |
|||
} |
|||
|
|||
public override void WriteValue(uint value) |
|||
{ |
|||
bsonWriter.WriteInt32((int)value); |
|||
} |
|||
|
|||
public override void WriteValue(long value) |
|||
{ |
|||
bsonWriter.WriteInt64(value); |
|||
} |
|||
|
|||
public override void WriteValue(ulong value) |
|||
{ |
|||
bsonWriter.WriteInt64((long)value); |
|||
} |
|||
|
|||
public override void WriteValue(float value) |
|||
{ |
|||
bsonWriter.WriteDouble(value); |
|||
} |
|||
|
|||
public override void WriteValue(double value) |
|||
{ |
|||
bsonWriter.WriteDouble(value); |
|||
} |
|||
|
|||
public override void WriteValue(bool value) |
|||
{ |
|||
bsonWriter.WriteBoolean(value); |
|||
} |
|||
|
|||
public override void WriteValue(short value) |
|||
{ |
|||
bsonWriter.WriteInt32(value); |
|||
} |
|||
|
|||
public override void WriteValue(ushort value) |
|||
{ |
|||
bsonWriter.WriteInt32(value); |
|||
} |
|||
|
|||
public override void WriteValue(char value) |
|||
{ |
|||
bsonWriter.WriteInt32(value); |
|||
} |
|||
|
|||
public override void WriteValue(byte value) |
|||
{ |
|||
bsonWriter.WriteInt32(value); |
|||
} |
|||
|
|||
public override void WriteValue(sbyte value) |
|||
{ |
|||
bsonWriter.WriteInt32(value); |
|||
} |
|||
|
|||
public override void WriteValue(decimal value) |
|||
{ |
|||
bsonWriter.WriteDecimal128(value); |
|||
} |
|||
|
|||
public override void WriteValue(DateTime value) |
|||
{ |
|||
bsonWriter.WriteString(value.ToIso8601()); |
|||
} |
|||
|
|||
public override void WriteValue(DateTimeOffset value) |
|||
{ |
|||
bsonWriter.WriteString(value.UtcDateTime.ToIso8601()); |
|||
} |
|||
|
|||
public override void WriteValue(byte[]? value) |
|||
{ |
|||
if (value == null) |
|||
{ |
|||
bsonWriter.WriteNull(); |
|||
} |
|||
else |
|||
{ |
|||
bsonWriter.WriteBytes(value); |
|||
} |
|||
} |
|||
|
|||
public override void WriteValue(Uri? value) |
|||
{ |
|||
if (value == null) |
|||
{ |
|||
bsonWriter.WriteNull(); |
|||
} |
|||
else |
|||
{ |
|||
bsonWriter.WriteString(value.ToString()); |
|||
} |
|||
} |
|||
|
|||
public override void WriteValue(TimeSpan value) |
|||
{ |
|||
bsonWriter.WriteString(value.ToString()); |
|||
} |
|||
|
|||
public override void WriteValue(Guid value) |
|||
{ |
|||
bsonWriter.WriteString(value.ToString()); |
|||
} |
|||
|
|||
public override void Flush() |
|||
{ |
|||
bsonWriter.Flush(); |
|||
} |
|||
} |
|||
} |
|||
@ -1,31 +0,0 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Linq.Expressions; |
|||
using MongoDB.Driver; |
|||
|
|||
namespace Squidex.Infrastructure.MongoDb |
|||
{ |
|||
public sealed class FieldDefinitionBuilder<T> |
|||
{ |
|||
public static readonly FieldDefinitionBuilder<T> Instance = new FieldDefinitionBuilder<T>(); |
|||
|
|||
private FieldDefinitionBuilder() |
|||
{ |
|||
} |
|||
|
|||
public FieldDefinition<T, TResult> Build<TResult>(Expression<Func<T, TResult>> expression) |
|||
{ |
|||
return new ExpressionFieldDefinition<T, TResult>(expression); |
|||
} |
|||
|
|||
public FieldDefinition<T, TResult> Build<TResult>(string name) |
|||
{ |
|||
return new StringFieldDefinition<T, TResult>(name); |
|||
} |
|||
} |
|||
} |
|||
@ -1,98 +0,0 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using Newtonsoft.Json; |
|||
using Newtonsoft.Json.Serialization; |
|||
|
|||
namespace Squidex.Infrastructure.Json.Newtonsoft |
|||
{ |
|||
public sealed class ConverterContractResolver : CamelCasePropertyNamesContractResolver |
|||
{ |
|||
private readonly JsonConverter[] converters; |
|||
private readonly object lockObject = new object(); |
|||
private Dictionary<Type, JsonConverter?> converterCache = new Dictionary<Type, JsonConverter?>(); |
|||
|
|||
public ConverterContractResolver(params JsonConverter[] converters) |
|||
{ |
|||
NamingStrategy = new CamelCaseNamingStrategy(false, true); |
|||
|
|||
this.converters = converters; |
|||
|
|||
foreach (var converter in converters) |
|||
{ |
|||
if (converter is ISupportedTypes supportedTypes) |
|||
{ |
|||
foreach (var type in supportedTypes.SupportedTypes) |
|||
{ |
|||
converterCache[type] = converter; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
protected override JsonArrayContract CreateArrayContract(Type objectType) |
|||
{ |
|||
if (objectType.IsGenericType && objectType.GetGenericTypeDefinition() == typeof(IReadOnlyList<>)) |
|||
{ |
|||
var implementationType = typeof(List<>).MakeGenericType(objectType.GetGenericArguments()); |
|||
|
|||
return base.CreateArrayContract(implementationType); |
|||
} |
|||
|
|||
return base.CreateArrayContract(objectType); |
|||
} |
|||
|
|||
protected override JsonDictionaryContract CreateDictionaryContract(Type objectType) |
|||
{ |
|||
if (objectType.IsGenericType && objectType.GetGenericTypeDefinition() == typeof(IReadOnlyDictionary<,>)) |
|||
{ |
|||
var implementationType = typeof(Dictionary<,>).MakeGenericType(objectType.GetGenericArguments()); |
|||
|
|||
return base.CreateDictionaryContract(implementationType); |
|||
} |
|||
|
|||
return base.CreateDictionaryContract(objectType); |
|||
} |
|||
|
|||
protected override JsonConverter? ResolveContractConverter(Type objectType) |
|||
{ |
|||
var result = base.ResolveContractConverter(objectType); |
|||
|
|||
if (result != null) |
|||
{ |
|||
return result; |
|||
} |
|||
|
|||
var cache = converterCache; |
|||
|
|||
if (cache == null || !cache.TryGetValue(objectType, out result)) |
|||
{ |
|||
foreach (var converter in converters) |
|||
{ |
|||
if (converter.CanConvert(objectType)) |
|||
{ |
|||
result = converter; |
|||
} |
|||
} |
|||
|
|||
lock (lockObject) |
|||
{ |
|||
cache = converterCache; |
|||
|
|||
var updatedCache = (cache != null) |
|||
? new Dictionary<Type, JsonConverter?>(cache) |
|||
: new Dictionary<Type, JsonConverter?>(); |
|||
updatedCache[objectType] = result; |
|||
|
|||
converterCache = updatedCache; |
|||
} |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
} |
|||
} |
|||
@ -1,49 +0,0 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using Newtonsoft.Json; |
|||
|
|||
namespace Squidex.Infrastructure.Json.Newtonsoft |
|||
{ |
|||
public abstract class JsonClassConverter<T> : JsonConverter, ISupportedTypes where T : class |
|||
{ |
|||
public virtual IEnumerable<Type> SupportedTypes |
|||
{ |
|||
get { yield return typeof(T); } |
|||
} |
|||
|
|||
public sealed override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) |
|||
{ |
|||
if (reader.TokenType == JsonToken.Null) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
return ReadValue(reader, objectType, serializer); |
|||
} |
|||
|
|||
protected abstract T? ReadValue(JsonReader reader, Type objectType, JsonSerializer serializer); |
|||
|
|||
public sealed override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) |
|||
{ |
|||
if (value == null) |
|||
{ |
|||
writer.WriteNull(); |
|||
return; |
|||
} |
|||
|
|||
WriteValue(writer, (T)value, serializer); |
|||
} |
|||
|
|||
protected abstract void WriteValue(JsonWriter writer, T value, JsonSerializer serializer); |
|||
|
|||
public override bool CanConvert(Type objectType) |
|||
{ |
|||
return objectType == typeof(T); |
|||
} |
|||
} |
|||
} |
|||
@ -1,207 +0,0 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using Newtonsoft.Json; |
|||
using Squidex.Infrastructure.Json.Objects; |
|||
|
|||
#pragma warning disable RECS0018 // Comparison of floating point numbers with equality operator
|
|||
|
|||
namespace Squidex.Infrastructure.Json.Newtonsoft |
|||
{ |
|||
public class JsonValueConverter : JsonConverter, ISupportedTypes |
|||
{ |
|||
private readonly HashSet<Type> supportedTypes = new HashSet<Type> |
|||
{ |
|||
typeof(JsonValue) |
|||
}; |
|||
|
|||
public virtual IEnumerable<Type> SupportedTypes |
|||
{ |
|||
get => supportedTypes; |
|||
} |
|||
|
|||
public override object ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) |
|||
{ |
|||
var previousDateParseHandling = reader.DateParseHandling; |
|||
|
|||
reader.DateParseHandling = DateParseHandling.None; |
|||
try |
|||
{ |
|||
return ReadJsonCore(reader); |
|||
} |
|||
finally |
|||
{ |
|||
reader.DateParseHandling = previousDateParseHandling; |
|||
} |
|||
} |
|||
|
|||
private static JsonValue ReadJsonCore(JsonReader reader) |
|||
{ |
|||
switch (reader.TokenType) |
|||
{ |
|||
case JsonToken.Null: |
|||
return default; |
|||
case JsonToken.Undefined: |
|||
return default; |
|||
case JsonToken.String: |
|||
return new JsonValue((string)reader.Value!); |
|||
case JsonToken.Integer: |
|||
return new JsonValue((long)reader.Value!); |
|||
case JsonToken.Float: |
|||
return new JsonValue((double)reader.Value!); |
|||
case JsonToken.Boolean: |
|||
return (bool)reader.Value! ? JsonValue.True : JsonValue.False; |
|||
case JsonToken.StartObject: |
|||
{ |
|||
var result = new JsonObject(4); |
|||
|
|||
Dictionary<string, JsonValue> dictionary = result; |
|||
|
|||
while (reader.Read()) |
|||
{ |
|||
switch (reader.TokenType) |
|||
{ |
|||
case JsonToken.PropertyName: |
|||
var propertyName = reader.Value!.ToString()!; |
|||
|
|||
if (!reader.Read()) |
|||
{ |
|||
ThrowInvalidObjectException(); |
|||
} |
|||
|
|||
var value = ReadJsonCore(reader); |
|||
|
|||
dictionary.Add(propertyName, value); |
|||
break; |
|||
case JsonToken.EndObject: |
|||
result.TrimExcess(); |
|||
|
|||
return new JsonValue(result); |
|||
} |
|||
} |
|||
|
|||
ThrowInvalidObjectException(); |
|||
return default!; |
|||
} |
|||
|
|||
case JsonToken.StartArray: |
|||
{ |
|||
var result = new JsonArray(4); |
|||
|
|||
while (reader.Read()) |
|||
{ |
|||
switch (reader.TokenType) |
|||
{ |
|||
case JsonToken.Comment: |
|||
continue; |
|||
case JsonToken.EndArray: |
|||
result.TrimExcess(); |
|||
|
|||
return new JsonValue(result); |
|||
default: |
|||
var value = ReadJsonCore(reader); |
|||
|
|||
result.Add(value); |
|||
break; |
|||
} |
|||
} |
|||
|
|||
ThrowInvalidArrayException(); |
|||
return default!; |
|||
} |
|||
|
|||
case JsonToken.Comment: |
|||
reader.Read(); |
|||
break; |
|||
} |
|||
|
|||
ThrowUnsupportedTypeException(); |
|||
return default; |
|||
} |
|||
|
|||
private static void ThrowUnsupportedTypeException() |
|||
{ |
|||
throw new JsonSerializationException("Unsupported type."); |
|||
} |
|||
|
|||
private static void ThrowInvalidArrayException() |
|||
{ |
|||
throw new JsonSerializationException("Unexpected end when reading Array."); |
|||
} |
|||
|
|||
private static void ThrowInvalidObjectException() |
|||
{ |
|||
throw new JsonSerializationException("Unexpected end when reading Object."); |
|||
} |
|||
|
|||
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) |
|||
{ |
|||
if (value == null) |
|||
{ |
|||
writer.WriteNull(); |
|||
return; |
|||
} |
|||
|
|||
WriteJson(writer, (JsonValue)value); |
|||
} |
|||
|
|||
private static void WriteJson(JsonWriter writer, JsonValue value) |
|||
{ |
|||
switch (value.Value) |
|||
{ |
|||
case null: |
|||
writer.WriteNull(); |
|||
break; |
|||
case bool b: |
|||
writer.WriteValue(b); |
|||
break; |
|||
case string s: |
|||
writer.WriteValue(s); |
|||
break; |
|||
case double n: |
|||
if (n % 1 == 0) |
|||
{ |
|||
writer.WriteValue((long)n); |
|||
} |
|||
else |
|||
{ |
|||
writer.WriteValue(n); |
|||
} |
|||
|
|||
break; |
|||
case JsonArray a: |
|||
writer.WriteStartArray(); |
|||
|
|||
foreach (var item in a) |
|||
{ |
|||
WriteJson(writer, item); |
|||
} |
|||
|
|||
writer.WriteEndArray(); |
|||
break; |
|||
|
|||
case JsonObject o: |
|||
writer.WriteStartObject(); |
|||
|
|||
foreach (var (key, jsonValue) in o) |
|||
{ |
|||
writer.WritePropertyName(key); |
|||
|
|||
WriteJson(writer, jsonValue); |
|||
} |
|||
|
|||
writer.WriteEndObject(); |
|||
break; |
|||
} |
|||
} |
|||
|
|||
public override bool CanConvert(Type objectType) |
|||
{ |
|||
return supportedTypes.Contains(objectType); |
|||
} |
|||
} |
|||
} |
|||
@ -1,98 +0,0 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using Newtonsoft.Json; |
|||
using NewtonsoftException = Newtonsoft.Json.JsonException; |
|||
|
|||
namespace Squidex.Infrastructure.Json.Newtonsoft |
|||
{ |
|||
public sealed class NewtonsoftJsonSerializer : IJsonSerializer |
|||
{ |
|||
private readonly JsonSerializerSettings settings; |
|||
private readonly JsonSerializer serializer; |
|||
|
|||
public NewtonsoftJsonSerializer(JsonSerializerSettings settings) |
|||
{ |
|||
Guard.NotNull(settings); |
|||
|
|||
this.settings = settings; |
|||
|
|||
serializer = JsonSerializer.Create(settings); |
|||
} |
|||
|
|||
public string Serialize<T>(T value, bool intented = false) |
|||
{ |
|||
var formatting = intented ? Formatting.Indented : Formatting.None; |
|||
|
|||
return JsonConvert.SerializeObject(value, formatting, settings); |
|||
} |
|||
|
|||
public void Serialize<T>(T value, Stream stream, bool leaveOpen = false) |
|||
{ |
|||
try |
|||
{ |
|||
using (var writer = new StreamWriter(stream, leaveOpen: leaveOpen)) |
|||
{ |
|||
serializer.Serialize(writer, value); |
|||
|
|||
writer.Flush(); |
|||
} |
|||
} |
|||
catch (NewtonsoftException ex) |
|||
{ |
|||
ThrowHelper.JsonException(ex.Message, ex); |
|||
} |
|||
} |
|||
|
|||
public T Deserialize<T>(string value, Type? actualType = null) |
|||
{ |
|||
try |
|||
{ |
|||
using (var textReader = new StringReader(value)) |
|||
{ |
|||
actualType ??= typeof(T); |
|||
|
|||
using (var reader = GetReader(textReader)) |
|||
{ |
|||
return (T)serializer.Deserialize(reader, actualType)!; |
|||
} |
|||
} |
|||
} |
|||
catch (NewtonsoftException ex) |
|||
{ |
|||
ThrowHelper.JsonException(ex.Message, ex); |
|||
return default!; |
|||
} |
|||
} |
|||
|
|||
public T Deserialize<T>(Stream stream, Type? actualType = null, bool leaveOpen = false) |
|||
{ |
|||
try |
|||
{ |
|||
using (var textReader = new StreamReader(stream, leaveOpen: leaveOpen)) |
|||
{ |
|||
actualType ??= typeof(T); |
|||
|
|||
using (var reader = GetReader(textReader)) |
|||
{ |
|||
return (T)serializer.Deserialize(reader, actualType)!; |
|||
} |
|||
} |
|||
} |
|||
catch (NewtonsoftException ex) |
|||
{ |
|||
ThrowHelper.JsonException(ex.Message, ex); |
|||
return default!; |
|||
} |
|||
} |
|||
|
|||
private static JsonTextReader GetReader(TextReader textReader) |
|||
{ |
|||
return new JsonTextReader(textReader); |
|||
} |
|||
} |
|||
} |
|||
@ -1,30 +0,0 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using Newtonsoft.Json; |
|||
|
|||
namespace Squidex.Infrastructure.Json.Newtonsoft |
|||
{ |
|||
public sealed class SurrogateConverter<T, TSurrogate> : JsonClassConverter<T> where T : class where TSurrogate : ISurrogate<T>, new() |
|||
{ |
|||
protected override T? ReadValue(JsonReader reader, Type objectType, JsonSerializer serializer) |
|||
{ |
|||
var surrogate = serializer.Deserialize<TSurrogate>(reader); |
|||
|
|||
return surrogate?.ToSource(); |
|||
} |
|||
|
|||
protected override void WriteValue(JsonWriter writer, T value, JsonSerializer serializer) |
|||
{ |
|||
var surrogate = new TSurrogate(); |
|||
|
|||
surrogate.FromSource(value); |
|||
|
|||
serializer.Serialize(writer, surrogate); |
|||
} |
|||
} |
|||
} |
|||
@ -1,50 +0,0 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System.ComponentModel; |
|||
using Newtonsoft.Json; |
|||
|
|||
namespace Squidex.Infrastructure.Json.Newtonsoft |
|||
{ |
|||
public sealed class TypeConverterJsonConverter<T> : JsonConverter, ISupportedTypes |
|||
{ |
|||
private readonly TypeConverter typeConverter = TypeDescriptor.GetConverter(typeof(T)); |
|||
|
|||
public IEnumerable<Type> SupportedTypes |
|||
{ |
|||
get { yield return typeof(T); } |
|||
} |
|||
|
|||
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) |
|||
{ |
|||
if (reader.TokenType == JsonToken.Null) |
|||
{ |
|||
return default(T); |
|||
} |
|||
|
|||
try |
|||
{ |
|||
return typeConverter.ConvertFromInvariantString(reader.Value?.ToString()!); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
ThrowHelper.JsonException("Error while converting from string.", ex); |
|||
return default; |
|||
} |
|||
} |
|||
|
|||
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) |
|||
{ |
|||
writer.WriteValue(typeConverter.ConvertToInvariantString(value)); |
|||
} |
|||
|
|||
public override bool CanConvert(Type objectType) |
|||
{ |
|||
return objectType == typeof(T); |
|||
} |
|||
} |
|||
} |
|||
@ -1,45 +0,0 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using Newtonsoft.Json.Serialization; |
|||
using Squidex.Infrastructure.Reflection; |
|||
|
|||
namespace Squidex.Infrastructure.Json.Newtonsoft |
|||
{ |
|||
public sealed class TypeNameSerializationBinder : DefaultSerializationBinder |
|||
{ |
|||
private readonly TypeNameRegistry typeNameRegistry; |
|||
|
|||
public TypeNameSerializationBinder(TypeNameRegistry typeNameRegistry) |
|||
{ |
|||
this.typeNameRegistry = typeNameRegistry; |
|||
} |
|||
|
|||
public override Type BindToType(string? assemblyName, string typeName) |
|||
{ |
|||
var type = typeNameRegistry.GetTypeOrNull(typeName); |
|||
|
|||
return type ?? base.BindToType(assemblyName, typeName); |
|||
} |
|||
|
|||
public override void BindToName(Type serializedType, out string? assemblyName, out string? typeName) |
|||
{ |
|||
assemblyName = null; |
|||
|
|||
var name = typeNameRegistry.GetNameOrNull(serializedType); |
|||
|
|||
if (name != null) |
|||
{ |
|||
typeName = name; |
|||
} |
|||
else |
|||
{ |
|||
base.BindToName(serializedType, out assemblyName, out typeName); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,16 +0,0 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using GeoJSON.Net.Converters; |
|||
|
|||
namespace Squidex.Infrastructure.Json.Newtonsoft |
|||
{ |
|||
public sealed class WriteonlyGeoJsonConverter : GeoJsonConverter |
|||
{ |
|||
public override bool CanWrite => false; |
|||
} |
|||
} |
|||
@ -0,0 +1,54 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Text.Json; |
|||
using Squidex.Infrastructure.Reflection; |
|||
|
|||
namespace Squidex.Infrastructure.Json.System |
|||
{ |
|||
public sealed class InheritanceConverter<T> : InheritanceConverterBase<T> where T : notnull |
|||
{ |
|||
private readonly TypeNameRegistry typeNameRegistry; |
|||
|
|||
public InheritanceConverter(TypeNameRegistry typeNameRegistry) |
|||
: base("$type") |
|||
{ |
|||
this.typeNameRegistry = typeNameRegistry; |
|||
} |
|||
|
|||
public override Type GetDiscriminatorType(string name, Type typeToConvert) |
|||
{ |
|||
var typeInfo = typeNameRegistry.GetTypeOrNull(name); |
|||
|
|||
if (typeInfo == null) |
|||
{ |
|||
typeInfo = Type.GetType(name); |
|||
} |
|||
|
|||
if (typeInfo == null) |
|||
{ |
|||
ThrowHelper.JsonException($"Object has invalid discriminator '{name}'."); |
|||
return default!; |
|||
} |
|||
|
|||
return typeInfo; |
|||
} |
|||
|
|||
public override string GetDiscriminatorValue(Type type) |
|||
{ |
|||
var typeName = typeNameRegistry.GetNameOrNull(type); |
|||
|
|||
if (typeName == null) |
|||
{ |
|||
// Use the type name as a fallback.
|
|||
typeName = type.AssemblyQualifiedName!; |
|||
} |
|||
|
|||
return typeName; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,95 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Text.Json; |
|||
using System.Text.Json.Serialization; |
|||
using Squidex.Infrastructure.ObjectPool; |
|||
|
|||
namespace Squidex.Infrastructure.Json.System |
|||
{ |
|||
public abstract class InheritanceConverterBase<T> : JsonConverter<T> where T : notnull |
|||
{ |
|||
private readonly JsonEncodedText discriminatorProperty; |
|||
|
|||
public string DiscriminatorName { get; } |
|||
|
|||
protected InheritanceConverterBase(string discriminatorName) |
|||
{ |
|||
discriminatorProperty = JsonEncodedText.Encode(discriminatorName); |
|||
|
|||
DiscriminatorName = discriminatorName; |
|||
} |
|||
|
|||
public abstract Type GetDiscriminatorType(string name, Type typeToConvert); |
|||
|
|||
public abstract string GetDiscriminatorValue(Type type); |
|||
|
|||
public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) |
|||
{ |
|||
// Creating a copy of the reader (The derived deserialisation has to be done from the start)
|
|||
Utf8JsonReader typeReader = reader; |
|||
|
|||
if (typeReader.TokenType != JsonTokenType.StartObject) |
|||
{ |
|||
throw new JsonException(); |
|||
} |
|||
|
|||
if (!typeReader.Read() || typeReader.TokenType != JsonTokenType.PropertyName) |
|||
{ |
|||
throw new JsonException(); |
|||
} |
|||
|
|||
var propertyName = typeReader.GetString(); |
|||
|
|||
if (typeReader.Read() && typeReader.TokenType == JsonTokenType.String && propertyName == DiscriminatorName) |
|||
{ |
|||
var type = GetDiscriminatorType(typeReader.GetString()!, typeToConvert); |
|||
|
|||
return (T?)JsonSerializer.Deserialize(ref reader, type, options); |
|||
} |
|||
else |
|||
{ |
|||
using var document = JsonDocument.ParseValue(ref reader); |
|||
|
|||
if (!document.RootElement.TryGetProperty(DiscriminatorName, out var discriminator)) |
|||
{ |
|||
ThrowHelper.JsonException($"Object has no discriminator '{DiscriminatorName}."); |
|||
return default!; |
|||
} |
|||
|
|||
var type = GetDiscriminatorType(discriminator.GetString()!, typeToConvert); |
|||
|
|||
using var bufferWriter = DefaultPools.MemoryStream.GetStream(); |
|||
|
|||
using (var writer = new Utf8JsonWriter(bufferWriter)) |
|||
{ |
|||
document.RootElement.WriteTo(writer); |
|||
} |
|||
|
|||
return (T?)JsonSerializer.Deserialize(bufferWriter.ToArray(), type, options); |
|||
} |
|||
} |
|||
|
|||
public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options) |
|||
{ |
|||
var name = GetDiscriminatorValue(value.GetType()); |
|||
|
|||
writer.WriteStartObject(); |
|||
writer.WriteString(discriminatorProperty, name); |
|||
|
|||
using (var document = JsonSerializer.SerializeToDocument(value, value.GetType(), options)) |
|||
{ |
|||
foreach (var property in document.RootElement.EnumerateObject()) |
|||
{ |
|||
property.WriteTo(writer); |
|||
} |
|||
} |
|||
|
|||
writer.WriteEndObject(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,72 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Text.Json; |
|||
using System.Text.Json.Serialization; |
|||
using SquidexJsonArray = Squidex.Infrastructure.Json.Objects.JsonArray; |
|||
using SquidexJsonObject = Squidex.Infrastructure.Json.Objects.JsonObject; |
|||
using SquidexJsonValue = Squidex.Infrastructure.Json.Objects.JsonValue; |
|||
|
|||
namespace Squidex.Infrastructure.Json.System |
|||
{ |
|||
public sealed class JsonValueConverter : JsonConverter<SquidexJsonValue> |
|||
{ |
|||
public override bool HandleNull => true; |
|||
|
|||
public override SquidexJsonValue Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) |
|||
{ |
|||
switch (reader.TokenType) |
|||
{ |
|||
case JsonTokenType.True: |
|||
return SquidexJsonValue.True; |
|||
case JsonTokenType.False: |
|||
return SquidexJsonValue.False; |
|||
case JsonTokenType.Null: |
|||
return SquidexJsonValue.Null; |
|||
case JsonTokenType.Number: |
|||
return SquidexJsonValue.Create(reader.GetDouble()); |
|||
case JsonTokenType.String: |
|||
return SquidexJsonValue.Create(reader.GetString()); |
|||
case JsonTokenType.StartObject: |
|||
return JsonSerializer.Deserialize<SquidexJsonObject>(ref reader, options); |
|||
case JsonTokenType.StartArray: |
|||
return JsonSerializer.Deserialize<SquidexJsonArray>(ref reader, options); |
|||
default: |
|||
ThrowHelper.NotSupportedException(); |
|||
return default; |
|||
} |
|||
} |
|||
|
|||
public override void Write(Utf8JsonWriter writer, SquidexJsonValue value, JsonSerializerOptions options) |
|||
{ |
|||
switch (value.Value) |
|||
{ |
|||
case null: |
|||
writer.WriteNullValue(); |
|||
break; |
|||
case bool b: |
|||
writer.WriteBooleanValue(b); |
|||
break; |
|||
case string s: |
|||
writer.WriteStringValue(s); |
|||
break; |
|||
case double n: |
|||
writer.WriteNumberValue(n); |
|||
break; |
|||
case SquidexJsonArray a: |
|||
JsonSerializer.Serialize(writer, a, options); |
|||
break; |
|||
case SquidexJsonObject o: |
|||
JsonSerializer.Serialize(writer, o, options); |
|||
break; |
|||
default: |
|||
ThrowHelper.NotSupportedException(); |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,69 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Linq.Expressions; |
|||
using System.Reflection; |
|||
using System.Reflection.Emit; |
|||
using System.Text.Json; |
|||
using System.Text.Json.Serialization; |
|||
using Squidex.Infrastructure.Collections; |
|||
|
|||
namespace Squidex.Infrastructure.Json.System |
|||
{ |
|||
public sealed class ReadonlyDictionaryConverterFactory : JsonConverterFactory |
|||
{ |
|||
private sealed class Converter<TKey, TValue, TInstance> : JsonConverter<TInstance> where TKey : notnull |
|||
{ |
|||
private readonly Type innerType = typeof(IReadOnlyDictionary<TKey, TValue>); |
|||
private readonly Func<IDictionary<TKey, TValue>, TInstance> creator; |
|||
|
|||
public Converter() |
|||
{ |
|||
creator = ReflectionHelper.CreateParameterizedConstructor<TInstance, IDictionary<TKey, TValue>>(); |
|||
} |
|||
|
|||
public override TInstance Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) |
|||
{ |
|||
var inner = JsonSerializer.Deserialize<Dictionary<TKey, TValue>>(ref reader, options)!; |
|||
|
|||
return creator(inner); |
|||
} |
|||
|
|||
public override void Write(Utf8JsonWriter writer, TInstance value, JsonSerializerOptions options) |
|||
{ |
|||
JsonSerializer.Serialize(writer, value, innerType, options); |
|||
} |
|||
} |
|||
|
|||
public override bool CanConvert(Type typeToConvert) |
|||
{ |
|||
return IsReadonlyDictionary(typeToConvert) || IsReadonlyDictionary(typeToConvert.BaseType); |
|||
} |
|||
|
|||
public override JsonConverter? CreateConverter(Type typeToConvert, JsonSerializerOptions options) |
|||
{ |
|||
var typeToCreate = IsReadonlyDictionary(typeToConvert) ? typeToConvert : typeToConvert.BaseType!; |
|||
|
|||
var concreteType = typeof(Converter<,,>).MakeGenericType( |
|||
new Type[] |
|||
{ |
|||
typeToCreate.GetGenericArguments()[0], |
|||
typeToCreate.GetGenericArguments()[1], |
|||
typeToConvert |
|||
}); |
|||
|
|||
var converter = (JsonConverter)Activator.CreateInstance(concreteType)!; |
|||
|
|||
return converter; |
|||
} |
|||
|
|||
private static bool IsReadonlyDictionary(Type? type) |
|||
{ |
|||
return type != null && type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ReadonlyDictionary<,>); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,65 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Text.Json; |
|||
using System.Text.Json.Serialization; |
|||
using Squidex.Infrastructure.Collections; |
|||
|
|||
namespace Squidex.Infrastructure.Json.System |
|||
{ |
|||
public sealed class ReadonlyListConverterFactory : JsonConverterFactory |
|||
{ |
|||
private sealed class Converter<T, TInstance> : JsonConverter<TInstance> |
|||
{ |
|||
private readonly Type innerType = typeof(IReadOnlyList<T>); |
|||
private readonly Func<IList<T>, TInstance> creator; |
|||
|
|||
public Converter() |
|||
{ |
|||
creator = ReflectionHelper.CreateParameterizedConstructor<TInstance, IList<T>>(); |
|||
} |
|||
|
|||
public override TInstance Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) |
|||
{ |
|||
var inner = JsonSerializer.Deserialize<List<T>>(ref reader, options)!; |
|||
|
|||
return creator(inner); |
|||
} |
|||
|
|||
public override void Write(Utf8JsonWriter writer, TInstance value, JsonSerializerOptions options) |
|||
{ |
|||
JsonSerializer.Serialize(writer, value, innerType, options); |
|||
} |
|||
} |
|||
|
|||
public override bool CanConvert(Type typeToConvert) |
|||
{ |
|||
return IsReadonlyList(typeToConvert) || IsReadonlyList(typeToConvert.BaseType); |
|||
} |
|||
|
|||
public override JsonConverter? CreateConverter(Type typeToConvert, JsonSerializerOptions options) |
|||
{ |
|||
var typeToCreate = IsReadonlyList(typeToConvert) ? typeToConvert : typeToConvert.BaseType!; |
|||
|
|||
var concreteType = typeof(Converter<,>).MakeGenericType( |
|||
new Type[] |
|||
{ |
|||
typeToCreate.GetGenericArguments()[0], |
|||
typeToConvert, |
|||
}); |
|||
|
|||
var converter = (JsonConverter)Activator.CreateInstance(concreteType)!; |
|||
|
|||
return converter; |
|||
} |
|||
|
|||
private static bool IsReadonlyList(Type? type) |
|||
{ |
|||
return type != null && type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ReadonlyList<>); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,46 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Reflection; |
|||
using System.Reflection.Emit; |
|||
|
|||
namespace Squidex.Infrastructure.Json.System |
|||
{ |
|||
internal static class ReflectionHelper |
|||
{ |
|||
public static Func<TInput, TInstance> CreateParameterizedConstructor<TInstance, TInput>() |
|||
{ |
|||
var method = CreateParameterizedConstructor(typeof(TInstance), typeof(TInput)); |
|||
|
|||
return method.CreateDelegate<Func<TInput, TInstance>>(); |
|||
} |
|||
|
|||
private static DynamicMethod CreateParameterizedConstructor(Type type, Type parameterType) |
|||
{ |
|||
var constructor = |
|||
type.GetConstructors() |
|||
.Single(x => |
|||
x.GetParameters().Length == 1 && |
|||
x.GetParameters()[0].ParameterType == parameterType); |
|||
|
|||
var dynamicMethod = new DynamicMethod( |
|||
ConstructorInfo.ConstructorName, |
|||
type, |
|||
new[] { parameterType }, |
|||
typeof(ReflectionHelper).Module, |
|||
true); |
|||
|
|||
var generator = dynamicMethod.GetILGenerator(); |
|||
|
|||
generator.Emit(OpCodes.Ldarg_0); |
|||
generator.Emit(OpCodes.Newobj, constructor); |
|||
generator.Emit(OpCodes.Ret); |
|||
|
|||
return dynamicMethod; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,62 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System.ComponentModel; |
|||
using System.Text.Json; |
|||
using System.Text.Json.Serialization; |
|||
|
|||
namespace Squidex.Infrastructure.Json.System |
|||
{ |
|||
public sealed class StringConverter<T> : JsonConverter<T> where T : notnull |
|||
{ |
|||
private readonly Func<string, T> convertFromString; |
|||
private readonly Func<T, string?> convertToString; |
|||
|
|||
public StringConverter(Func<string, T> convertFromString, Func<T, string?>? convertToString = null) |
|||
{ |
|||
this.convertFromString = convertFromString; |
|||
this.convertToString = convertToString ?? (x => x.ToString()); |
|||
} |
|||
|
|||
public StringConverter() |
|||
{ |
|||
var typeConverter = TypeDescriptor.GetConverter(typeof(T)); |
|||
|
|||
convertFromString = x => (T)typeConverter.ConvertFromInvariantString(x)!; |
|||
convertToString = x => typeConverter.ConvertToInvariantString(x)!; |
|||
} |
|||
|
|||
public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) |
|||
{ |
|||
var text = reader.GetString(); |
|||
try |
|||
{ |
|||
return convertFromString(text!); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
ThrowHelper.JsonException("Error while converting from string.", ex); |
|||
return default; |
|||
} |
|||
} |
|||
|
|||
public override T ReadAsPropertyName(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) |
|||
{ |
|||
return convertFromString(reader.GetString()!); |
|||
} |
|||
|
|||
public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options) |
|||
{ |
|||
writer.WriteStringValue(convertToString(value)); |
|||
} |
|||
|
|||
public override void WriteAsPropertyName(Utf8JsonWriter writer, T value, JsonSerializerOptions options) |
|||
{ |
|||
writer.WritePropertyName(convertToString(value)!); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,31 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Text.Json; |
|||
using System.Text.Json.Serialization; |
|||
|
|||
namespace Squidex.Infrastructure.Json.System |
|||
{ |
|||
public sealed class SurrogateJsonConverter<T, TSurrogate> : JsonConverter<T> where T : class where TSurrogate : ISurrogate<T>, new() |
|||
{ |
|||
public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) |
|||
{ |
|||
var surrogate = JsonSerializer.Deserialize<TSurrogate>(ref reader, options); |
|||
|
|||
return surrogate?.ToSource(); |
|||
} |
|||
|
|||
public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options) |
|||
{ |
|||
var surrogate = new TSurrogate(); |
|||
|
|||
surrogate.FromSource(value); |
|||
|
|||
JsonSerializer.Serialize(writer, surrogate, options); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,108 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Text.Json; |
|||
using SystemJsonException = System.Text.Json.JsonException; |
|||
|
|||
namespace Squidex.Infrastructure.Json.System |
|||
{ |
|||
public sealed class SystemJsonSerializer : IJsonSerializer |
|||
{ |
|||
private readonly JsonSerializerOptions optionsNormal; |
|||
private readonly JsonSerializerOptions optionsIndented; |
|||
|
|||
public SystemJsonSerializer(JsonSerializerOptions options) |
|||
{ |
|||
optionsNormal = new JsonSerializerOptions(options) |
|||
{ |
|||
WriteIndented = false |
|||
}; |
|||
|
|||
optionsIndented = new JsonSerializerOptions(options) |
|||
{ |
|||
WriteIndented = true |
|||
}; |
|||
} |
|||
|
|||
public T Deserialize<T>(string value, Type? actualType = null) |
|||
{ |
|||
try |
|||
{ |
|||
return (T)JsonSerializer.Deserialize(value, actualType ?? typeof(T), optionsNormal)!; |
|||
} |
|||
catch (SystemJsonException ex) |
|||
{ |
|||
ThrowHelper.JsonException(ex.Message, ex); |
|||
return default!; |
|||
} |
|||
} |
|||
|
|||
public T Deserialize<T>(Stream stream, Type? actualType = null, bool leaveOpen = false) |
|||
{ |
|||
try |
|||
{ |
|||
return (T)JsonSerializer.Deserialize(stream, actualType ?? typeof(T), optionsNormal)!; |
|||
} |
|||
catch (SystemJsonException ex) |
|||
{ |
|||
ThrowHelper.JsonException(ex.Message, ex); |
|||
return default!; |
|||
} |
|||
finally |
|||
{ |
|||
if (!leaveOpen) |
|||
{ |
|||
stream.Dispose(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
public string Serialize<T>(T value, bool indented = false) |
|||
{ |
|||
return Serialize(value, typeof(T), indented); |
|||
} |
|||
|
|||
public string Serialize(object? value, Type type, bool intented = false) |
|||
{ |
|||
try |
|||
{ |
|||
var options = intented ? optionsIndented : optionsNormal; |
|||
|
|||
return JsonSerializer.Serialize(value, type, options); |
|||
} |
|||
catch (SystemJsonException ex) |
|||
{ |
|||
ThrowHelper.JsonException(ex.Message, ex); |
|||
return default!; |
|||
} |
|||
} |
|||
|
|||
public void Serialize<T>(T value, Stream stream, bool leaveOpen = false) |
|||
{ |
|||
Serialize(value, typeof(T), stream, leaveOpen); |
|||
} |
|||
|
|||
public void Serialize(object? value, Type type, Stream stream, bool leaveOpen = false) |
|||
{ |
|||
try |
|||
{ |
|||
JsonSerializer.Serialize(stream, value, optionsNormal); |
|||
} |
|||
catch (SystemJsonException ex) |
|||
{ |
|||
ThrowHelper.JsonException(ex.Message, ex); |
|||
} |
|||
finally |
|||
{ |
|||
if (!leaveOpen) |
|||
{ |
|||
stream.Dispose(); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue