Skip to content
This repository has been archived by the owner on Dec 24, 2022. It is now read-only.

Commit

Permalink
Resolve scoped TypeAttr
Browse files Browse the repository at this point in the history
  • Loading branch information
mythz committed Oct 22, 2020
1 parent eac56b5 commit 4708869
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 15 deletions.
3 changes: 1 addition & 2 deletions src/ServiceStack.Text/Common/DeserializeTypeRefJson.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ internal static class DeserializeTypeRefJson
{
private static readonly JsonTypeSerializer Serializer = (JsonTypeSerializer)JsonTypeSerializer.Instance;

static readonly ReadOnlyMemory<char> typeAttr = JsWriter.TypeAttr.AsMemory();

internal static object StringToType(ReadOnlySpan<char> strType,
TypeConfig typeConfig,
EmptyCtorDelegate ctorFn,
Expand All @@ -34,6 +32,7 @@ internal static object StringToType(ReadOnlySpan<char> strType,
return ctorFn();

var config = JsConfig.GetConfig();
var typeAttr = config.TypeAttrMemory;

object instance = null;
var lenient = config.PropertyConvention == PropertyConvention.Lenient;
Expand Down
4 changes: 0 additions & 4 deletions src/ServiceStack.Text/JsConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -406,21 +406,17 @@ public static string TypeAttr
{
var config = Config.AssertNotInit();
config.TypeAttr = value;
config.JsonTypeAttrInObject = JsonTypeSerializer.GetTypeAttrInObject(value);
config.JsvTypeAttrInObject = JsvTypeSerializer.GetTypeAttrInObject(value);
}
}

internal static string JsonTypeAttrInObject
{
get => JsConfigScope.Current != null ? JsConfigScope.Current.JsonTypeAttrInObject : Config.Instance.JsonTypeAttrInObject;
set => Config.AssertNotInit().JsonTypeAttrInObject = value;
}

internal static string JsvTypeAttrInObject
{
get => JsConfigScope.Current != null ? JsConfigScope.Current.JsvTypeAttrInObject : Config.Instance.JsvTypeAttrInObject;
set => Config.AssertNotInit().JsvTypeAttrInObject = value;
}

public static Func<Type, string> TypeWriter
Expand Down
27 changes: 20 additions & 7 deletions src/ServiceStack.Text/JsConfigScope.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,27 @@ private Config(Config config)
public bool TreatEnumAsInteger { get; set; }
public bool ExcludeTypeInfo { get; set; }
public bool IncludeTypeInfo { get; set; }
public string TypeAttr { get; set; }

private string typeAttr;
public string TypeAttr
{
get => typeAttr;
set
{
typeAttrSpan = null;
jsonTypeAttrInObject = null;
jsvTypeAttrInObject = null;
typeAttr = value;
}
}
ReadOnlyMemory<char>? typeAttrSpan = null;
public ReadOnlyMemory<char> TypeAttrMemory => typeAttrSpan ??= TypeAttr.AsMemory();
public string DateTimeFormat { get; set; }
internal string JsonTypeAttrInObject { get; set; }
internal string JsvTypeAttrInObject { get; set; }
private string jsonTypeAttrInObject;
internal string JsonTypeAttrInObject => jsonTypeAttrInObject ??= JsonTypeSerializer.GetTypeAttrInObject(TypeAttr);
private string jsvTypeAttrInObject;
internal string JsvTypeAttrInObject => jsvTypeAttrInObject ??= JsvTypeSerializer.GetTypeAttrInObject(TypeAttr);

public Func<Type, string> TypeWriter { get; set; }
public Func<string, Type> TypeFinder { get; set; }
public Func<string, object> ParsePrimitiveFn { get; set; }
Expand Down Expand Up @@ -180,8 +197,6 @@ public bool EmitLowercaseUnderscoreNames
IncludeTypeInfo = false,
TypeAttr = JsWriter.TypeAttr,
DateTimeFormat = null,
JsonTypeAttrInObject = JsonTypeSerializer.GetTypeAttrInObject(JsWriter.TypeAttr),
JsvTypeAttrInObject = JsvTypeSerializer.GetTypeAttrInObject(JsWriter.TypeAttr),
TypeWriter = AssemblyUtils.WriteType,
TypeFinder = AssemblyUtils.FindType,
ParsePrimitiveFn = null,
Expand Down Expand Up @@ -222,8 +237,6 @@ public Config Populate(Config config)
IncludeTypeInfo = config.IncludeTypeInfo;
TypeAttr = config.TypeAttr;
DateTimeFormat = config.DateTimeFormat;
JsonTypeAttrInObject = config.JsonTypeAttrInObject;
JsvTypeAttrInObject = config.JsvTypeAttrInObject;
TypeWriter = config.TypeWriter;
TypeFinder = config.TypeFinder;
ParsePrimitiveFn = config.ParsePrimitiveFn;
Expand Down
3 changes: 1 addition & 2 deletions src/ServiceStack.Text/TypeConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@ public static class TypeConfig<T>
{
internal static TypeConfig config;

static TypeConfig Config =>
config ?? (config = Create());
static TypeConfig Config => config ??= Create();

public static PropertyInfo[] Properties
{
Expand Down
31 changes: 31 additions & 0 deletions tests/ServiceStack.Text.Tests/RuntimeSerializationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,37 @@ public void Can_serialize_JS_literal_into_DTO()
JS.UnConfigure();
}

[Test]
public void ServiceStack_AllowRuntimeType()
{
// Initialize static delegate to allow all types to be deserialized with the type attribute
JsConfig.AllowRuntimeType = _ => true;
JsConfig.TypeAttr = "$type";
var example = new Example { Property = new MyProperty { Value = "Hello serializer" } };

var serialized = JsonSerializer.SerializeToString(example);
var deserialized = JsonSerializer.DeserializeFromString<Example>(serialized);
Assert.IsNotNull(deserialized?.Property);

// Now the same process with a config scope that has a TypeAttr that differs from the global TypeAttr value
using var scope = JsConfig.With(new Config { TypeAttr = "_type" });
serialized = JsonSerializer.SerializeToString(example);
deserialized = JsonSerializer.DeserializeFromString<Example>(serialized);
Assert.IsNotNull(deserialized?.Property);

JsConfig.Reset();
}

private class Example
{
public IProperty Property { get; set; }
}
private interface IProperty
{
}
private class MyProperty : IProperty
{
public string Value { get; set; }
}
}
}

0 comments on commit 4708869

Please sign in to comment.