Skip to content
Snippets Groups Projects
Commit ce51dea2 authored by Richard Marcus's avatar Richard Marcus
Browse files

added jsonsubtypes as plain folder

parent 6d214b6e
No related branches found
No related tags found
No related merge requests found
Showing
with 1009 additions and 0 deletions
###############################
# Core EditorConfig Options #
###############################
root = true
# All files
[*]
indent_style = space
# Code files
[*.{cs,csx,vb,vbx}]
indent_size = 4
insert_final_newline = true
charset = utf-8-bom
/packages
*.suo
bin
obj
*.user
/TestResults
*.ide
/.idea
/.vs
# Local History for Visual Studio
.localhistory/
\ No newline at end of file
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
## [1.7.0] - 2020-03-28
### Added
- Fallback to JSONPath to allow nested field as a deserialization property. #89
- Bump Newtonsoft.Json from 11.0.2 to 12.0.3 #88
- Implements dynamic registration for subtype detection by property presence. #50
### Fixed
- JsonSubtypes does not respect naming strategy for discriminator property value #80
- Fix infinite loop when specifying name of abstract base class as discriminator #83
- Serializing base class with discriminator property results in KeyNotFoundException #79
## [1.6.0] - 2019-06-25
### Added
- Support for multiple discriminators on single type #66
- Support for per inheritance level discriminators #60
- Support specifying a falback sub type if none matched #63
- Provide NuGet package with strong name #75
- Changelog history and documentation arround versionning
## [1.5.2] - 2019-01-19
### Security
- Arbitrary constructor invocation #56
## [1.5.1] - 2018-10-15
### Fixed
- Read.me was imported by the nuget install #51
## [1.5.0] - 2018-08-27
### Added
- Ability to set the discriminator property order to first (see #46)
- Compatibility with JSON.NET 11.0.2 (see #47)
## [1.4.0] - 2018-04-18
### Added
- Support for both camel case and non camel case parameters #31
- Explicit support for netstandard2.0 #34
### Fixed
- Code refactoring to reduce the number of conditional compilation statements #36
## [1.3.1] - 2014-04-12
### Fixed
- fixed exception that was returned instead of thrown #32
## [1.3.0] - 2018-29-01
### Added
- De-/Serialization for sub-types without "type" property #13
- Option for avoiding mapping on the Parent #26
### Fixed
- Sonar (Coverage) analysis is broken #23
## [1.1.3] - 2017-11-15
### Fixed
- fixed support of framework net40 #21
## [1.1.2] - 2017-11-20
### Fixed
- fix #18 : Deserialisation is not thread safe
## [1.1.1] - 2017-09-22
### Fixed
- fix #11 Nuget packages doesn't work for .Net Framework projects
## [1.1.0] - 2017-09-19
### Added
- Parse string enum values #9.
## [1.0.0] - 2017-07-23
Initial release !
fileFormatVersion: 2
guid: 8dbd04d1390861e459e0fdba662dec7a
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/
fileFormatVersion: 2
guid: 2f8b79b30e1066e4fa55fc7d1d73610d
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 78aa215ce90c3b04eb6cf8d4e4f1b73c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: f4c875c153339654d94453d5b4bf7da5
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
File added
fileFormatVersion: 2
guid: 76648f4d8027077458aedbb4c7a56799
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 1e3c4601db6cf084dbedfe8f72a5d693
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
#if (NET35 || NET40)
using TypeInfo = System.Type;
#else
using System.Reflection;
#endif
namespace JsonSubTypes
{
// MIT License
//
// Copyright (c) 2017 Emmanuel Counasse
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
public class JsonSubtypes : JsonConverter
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = true)]
public class KnownSubTypeAttribute : Attribute
{
public Type SubType { get; }
public object AssociatedValue { get; }
public KnownSubTypeAttribute(Type subType, object associatedValue)
{
SubType = subType;
AssociatedValue = associatedValue;
}
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface)]
public class FallBackSubTypeAttribute : Attribute
{
public Type SubType { get; }
public FallBackSubTypeAttribute(Type subType)
{
SubType = subType;
}
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = true)]
public class KnownSubTypeWithPropertyAttribute : Attribute
{
public Type SubType { get; }
public string PropertyName { get; }
public KnownSubTypeWithPropertyAttribute(Type subType, string propertyName)
{
SubType = subType;
PropertyName = propertyName;
}
}
protected readonly string JsonDiscriminatorPropertyName;
[ThreadStatic] private static bool _isInsideRead;
[ThreadStatic] private static JsonReader _reader;
public override bool CanRead
{
get
{
if (!_isInsideRead)
return true;
return !string.IsNullOrEmpty(_reader.Path);
}
}
public override bool CanWrite => false;
public JsonSubtypes()
{
}
public JsonSubtypes(string jsonDiscriminatorPropertyName)
{
JsonDiscriminatorPropertyName = jsonDiscriminatorPropertyName;
}
public override bool CanConvert(Type objectType)
{
return false;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
JsonSerializer serializer)
{
return ReadJson(reader, objectType, serializer);
}
private object ReadJson(JsonReader reader, Type objectType, JsonSerializer serializer)
{
while (reader.TokenType == JsonToken.Comment)
reader.Read();
object value;
switch (reader.TokenType)
{
case JsonToken.Null:
value = null;
break;
case JsonToken.StartObject:
value = ReadObject(reader, objectType, serializer);
break;
case JsonToken.StartArray:
{
var elementType = GetElementType(objectType);
if (elementType == null)
{
throw CreateJsonReaderException(reader, $"Impossible to read JSON array to fill type: {objectType.Name}");
}
value = ReadArray(reader, objectType, elementType, serializer);
break;
}
default:
throw CreateJsonReaderException(reader, $"Unrecognized token: {reader.TokenType}");
}
return value;
}
private static JsonReaderException CreateJsonReaderException(JsonReader reader, string message)
{
var lineNumber = 0;
var linePosition = 0;
if (reader is IJsonLineInfo lineInfo && lineInfo.HasLineInfo())
{
lineNumber = lineInfo.LineNumber;
linePosition = lineInfo.LinePosition;
}
return new JsonReaderException(message, reader.Path, lineNumber, linePosition, null);
}
private IList ReadArray(JsonReader reader, Type targetType, Type elementType, JsonSerializer serializer)
{
var list = CreateCompatibleList(targetType, elementType);
while (reader.Read() && reader.TokenType != JsonToken.EndArray)
{
list.Add(ReadJson(reader, elementType, serializer));
}
if (!targetType.IsArray)
return list;
var array = Array.CreateInstance(elementType, list.Count);
list.CopyTo(array, 0);
return array;
}
private static IList CreateCompatibleList(Type targetContainerType, Type elementType)
{
var typeInfo = ToTypeInfo(targetContainerType);
if (typeInfo.IsArray || typeInfo.IsAbstract)
{
return (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(elementType));
}
return (IList)Activator.CreateInstance(targetContainerType);
}
private static Type GetElementType(Type arrayOrGenericContainer)
{
if (arrayOrGenericContainer.IsArray)
{
return arrayOrGenericContainer.GetElementType();
}
var genericTypeArguments = GetGenericTypeArguments(arrayOrGenericContainer);
return genericTypeArguments.FirstOrDefault();
}
private object ReadObject(JsonReader reader, Type objectType, JsonSerializer serializer)
{
var jObject = JObject.Load(reader);
var targetType = GetType(jObject, objectType, serializer) ?? objectType;
return ThreadStaticReadObject(reader, serializer, jObject, targetType);
}
private static JsonReader CreateAnotherReader(JToken jToken, JsonReader reader)
{
var jObjectReader = jToken.CreateReader();
jObjectReader.Culture = reader.Culture;
jObjectReader.CloseInput = reader.CloseInput;
jObjectReader.SupportMultipleContent = reader.SupportMultipleContent;
jObjectReader.DateTimeZoneHandling = reader.DateTimeZoneHandling;
jObjectReader.FloatParseHandling = reader.FloatParseHandling;
jObjectReader.DateFormatString = reader.DateFormatString;
jObjectReader.DateParseHandling = reader.DateParseHandling;
return jObjectReader;
}
private Type ResolveType(JObject jObject, Type parentType, JsonSerializer serializer)
{
Type resolvedType;
if (JsonDiscriminatorPropertyName == null)
{
resolvedType = GetTypeByPropertyPresence(jObject, parentType);
}
else
{
resolvedType = GetTypeFromDiscriminatorValue(jObject, parentType, serializer);
}
return resolvedType ?? GetFallbackSubType(parentType);
}
private Type GetType(JObject jObject, Type parentType, JsonSerializer serializer)
{
Type targetType = parentType;
JsonSubtypes lastTypeResolver = null;
JsonSubtypes currentTypeResolver = this;
var visitedTypes = new HashSet<Type> { targetType };
var jsonConverterCollection = serializer.Converters.OfType<JsonSubtypesByDiscriminatorValueConverter>().ToList();
while (currentTypeResolver != null && currentTypeResolver != lastTypeResolver)
{
targetType = currentTypeResolver.ResolveType(jObject, targetType, serializer);
if (!visitedTypes.Add(targetType))
{
break;
}
lastTypeResolver = currentTypeResolver;
jsonConverterCollection = jsonConverterCollection.Where(c => c != currentTypeResolver).ToList();
currentTypeResolver = GetTypeResolver(ToTypeInfo(targetType), jsonConverterCollection);
}
return targetType;
}
private JsonSubtypes GetTypeResolver(TypeInfo targetType, IEnumerable<JsonSubtypesByDiscriminatorValueConverter> jsonConverterCollection)
{
if (targetType == null)
{
return null;
}
var jsonConverterAttribute = GetAttribute<JsonConverterAttribute>(targetType);
if (jsonConverterAttribute != null && ToTypeInfo(typeof(JsonSubtypes)).IsAssignableFrom(ToTypeInfo(jsonConverterAttribute.ConverterType)))
{
return (JsonSubtypes)Activator.CreateInstance(jsonConverterAttribute.ConverterType, jsonConverterAttribute.ConverterParameters);
}
return jsonConverterCollection
.FirstOrDefault(c => c.CanConvert(ToType(targetType)));
}
private Type GetTypeByPropertyPresence(JObject jObject, Type parentType)
{
var knownSubTypeAttributes = GetTypesByPropertyPresence(parentType);
var types = knownSubTypeAttributes
.Select(knownType =>
{
if (TryGetValueInJson(jObject, knownType.Key, out JToken _))
return knownType.Value;
var token = jObject.SelectToken(knownType.Key);
if (token != null)
{
return knownType.Value;
}
return null;
})
.Where(type => type != null)
.ToArray();
if (types.Length == 1)
{
return types[0];
}
throw new JsonSerializationException("Ambiguous type resolution, expected only one type but got: " + String.Join(", ", types.Select(t => t.FullName).ToArray()));
}
internal virtual Dictionary<string, Type> GetTypesByPropertyPresence(Type parentType)
{
return GetAttributes<KnownSubTypeWithPropertyAttribute>(ToTypeInfo(parentType))
.ToDictionary(a => a.PropertyName, a => a.SubType);
}
private Type GetTypeFromDiscriminatorValue(JObject jObject, Type parentType, JsonSerializer serializer)
{
if (!TryGetValueInJson(jObject, JsonDiscriminatorPropertyName, out var discriminatorValue))
{
discriminatorValue = jObject.SelectToken(JsonDiscriminatorPropertyName);
}
if (discriminatorValue == null)
{
return null;
}
var typeMapping = GetSubTypeMapping(parentType);
if (typeMapping.Entries().Any())
{
return GetTypeFromMapping(typeMapping, discriminatorValue, serializer);
}
return GetTypeByName(discriminatorValue.Value<string>(), ToTypeInfo(parentType));
}
private static bool TryGetValueInJson(IDictionary<string, JToken> jObject, string propertyName, out JToken value)
{
if (jObject.TryGetValue(propertyName, out value))
{
return true;
}
var matchingProperty = jObject
.Keys
.FirstOrDefault(jsonProperty => string.Equals(jsonProperty, propertyName, StringComparison.OrdinalIgnoreCase));
if (matchingProperty == null)
{
return false;
}
value = jObject[matchingProperty];
return true;
}
private static Type GetTypeByName(string typeName, TypeInfo parentType)
{
if (typeName == null)
{
return null;
}
var insideAssembly = parentType.Assembly;
var parentTypeFullName = parentType.FullName;
var typeByName = insideAssembly.GetType(typeName);
if (parentTypeFullName != null && typeByName == null)
{
var searchLocation = parentTypeFullName.Substring(0, parentTypeFullName.Length - parentType.Name.Length);
typeByName = insideAssembly.GetType(searchLocation + typeName, false, true);
}
var typeByNameInfo = ToTypeInfo(typeByName);
if (typeByNameInfo != null && parentType.IsAssignableFrom(typeByNameInfo))
{
return typeByName;
}
return null;
}
private static Type GetTypeFromMapping(NullableDictionary<object, Type> typeMapping, JToken discriminatorToken, JsonSerializer serializer)
{
if (discriminatorToken.Type == JTokenType.Null)
{
typeMapping.TryGetValue(null, out Type targetType);
return targetType;
}
var key = typeMapping.NotNullKeys().FirstOrDefault();
if (key != null)
{
var targetLookupValueType = key.GetType();
var lookupValue = discriminatorToken.ToObject(targetLookupValueType, serializer);
if (typeMapping.TryGetValue(lookupValue, out Type targetType))
{
return targetType;
}
}
return null;
}
internal virtual NullableDictionary<object, Type> GetSubTypeMapping(Type type)
{
var dictionary = new NullableDictionary<object, Type>();
GetAttributes<KnownSubTypeAttribute>(ToTypeInfo(type))
.ToList()
.ForEach(x => dictionary.Add(x.AssociatedValue, x.SubType));
return dictionary;
}
internal virtual Type GetFallbackSubType(Type type)
{
return GetAttribute<FallBackSubTypeAttribute>(ToTypeInfo(type))?.SubType;
}
private static object ThreadStaticReadObject(JsonReader reader, JsonSerializer serializer, JToken jToken, Type targetType)
{
_reader = CreateAnotherReader(jToken, reader);
_isInsideRead = true;
try
{
return serializer.Deserialize(_reader, targetType);
}
finally
{
_isInsideRead = false;
}
}
private static IEnumerable<T> GetAttributes<T>(TypeInfo typeInfo) where T : Attribute
{
return typeInfo.GetCustomAttributes(false)
.OfType<T>();
}
private static T GetAttribute<T>(TypeInfo typeInfo) where T : Attribute
{
return GetAttributes<T>(typeInfo).FirstOrDefault();
}
private static IEnumerable<Type> GetGenericTypeArguments(Type type)
{
#if (NET35 || NET40)
return type.GetGenericArguments();
#else
return type.GenericTypeArguments;
#endif
}
internal static TypeInfo ToTypeInfo(Type type)
{
#if (NET35 || NET40)
return type;
#else
return type?.GetTypeInfo();
#endif
}
internal static Type ToType(TypeInfo typeInfo)
{
#if (NET35 || NET40)
return typeInfo;
#else
return typeInfo?.AsType();
#endif
}
}
}
fileFormatVersion: 2
guid: 1e427f6487939d44fa7981135e87a7e7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace JsonSubTypes
{
// MIT License
//
// Copyright (c) 2017 Emmanuel Counasse
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
internal class JsonSubtypesByDiscriminatorValueConverter : JsonSubtypesConverter
{
[ThreadStatic] private static bool _isInsideWrite;
[ThreadStatic] private static bool _allowNextWrite;
private readonly bool _addDiscriminatorFirst;
private readonly bool _serializeDiscriminatorProperty;
private readonly Dictionary<Type, object> _supportedTypes = new Dictionary<Type, object>();
private readonly NullableDictionary<object, Type> _subTypeMapping;
internal JsonSubtypesByDiscriminatorValueConverter(Type baseType, string discriminatorProperty,
NullableDictionary<object, Type> subTypeMapping, bool serializeDiscriminatorProperty, bool addDiscriminatorFirst, Type fallbackType) : base(baseType, discriminatorProperty, fallbackType)
{
_serializeDiscriminatorProperty = serializeDiscriminatorProperty;
_subTypeMapping = subTypeMapping;
_addDiscriminatorFirst = addDiscriminatorFirst;
foreach (var type in _subTypeMapping.Entries())
{
if (_supportedTypes.ContainsKey(type.Value))
{
if (_serializeDiscriminatorProperty)
{
throw new InvalidOperationException(
"Multiple discriminators on single type are not supported " +
"when discriminator serialization is enabled");
}
}
else
{
_supportedTypes.Add(type.Value, type.Key);
}
}
}
internal override NullableDictionary<object, Type> GetSubTypeMapping(Type type)
{
return _subTypeMapping;
}
public override bool CanConvert(Type objectType)
{
return base.CanConvert(objectType) || _supportedTypes.ContainsKey(objectType);
}
public override bool CanWrite
{
get
{
if (!_serializeDiscriminatorProperty)
return false;
if (!_isInsideWrite)
return true;
if (_allowNextWrite)
{
_allowNextWrite = false;
return true;
}
_allowNextWrite = true;
return false;
}
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
JObject jsonObj;
_isInsideWrite = true;
_allowNextWrite = false;
try
{
jsonObj = JObject.FromObject(value, serializer);
}
finally
{
_isInsideWrite = false;
}
if (!_supportedTypes.TryGetValue(value.GetType(), out var supportedType))
{
throw new JsonSerializationException("Impossible to serialize type: " + value.GetType().FullName + " because there is no registered mapping for the discriminator property");
}
var typeMappingPropertyValue = JToken.FromObject(supportedType, serializer);
if (_addDiscriminatorFirst)
{
jsonObj.AddFirst(new JProperty(JsonDiscriminatorPropertyName, typeMappingPropertyValue));
}
else
{
jsonObj.Add(JsonDiscriminatorPropertyName, typeMappingPropertyValue);
}
jsonObj.WriteTo(writer);
}
}
}
fileFormatVersion: 2
guid: a1452cb028e9c584cb53178f2ea70887
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using System;
using System.Collections.Generic;
namespace JsonSubTypes
{
internal class JsonSubtypesByPropertyPresenceConverter : JsonSubtypesConverter
{
private readonly Dictionary<string, Type> _jsonPropertyName2Type;
internal JsonSubtypesByPropertyPresenceConverter(Type baseType, Dictionary<string, Type> jsonProperty2Type, Type fallbackType) : base(baseType, fallbackType)
{
_jsonPropertyName2Type = jsonProperty2Type;
}
internal override Dictionary<string, Type> GetTypesByPropertyPresence(Type parentType)
{
return _jsonPropertyName2Type;
}
}
}
fileFormatVersion: 2
guid: d7fcded1d4a398143824a7e626cf1b19
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using System;
using System.Reflection;
namespace JsonSubTypes
{
// MIT License
//
// Copyright (c) 2017 Emmanuel Counasse
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
internal class JsonSubtypesConverter : JsonSubtypes
{
private readonly Type _baseType;
private readonly Type _fallbackType;
public JsonSubtypesConverter(Type baseType, Type fallbackType) : base()
{
_baseType = baseType;
_fallbackType = fallbackType;
}
public JsonSubtypesConverter(Type baseType, string jsonDiscriminatorPropertyName, Type fallbackType) : base(jsonDiscriminatorPropertyName)
{
_baseType = baseType;
_fallbackType = fallbackType;
}
internal override Type GetFallbackSubType(Type type)
{
return _fallbackType;
}
public override bool CanConvert(Type objectType)
{
return objectType == _baseType || ToTypeInfo(_baseType).IsAssignableFrom(ToTypeInfo(objectType));
}
}
}
fileFormatVersion: 2
guid: ef63f12cd6c544246a99ee6371f64ff5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using System;
using Newtonsoft.Json;
namespace JsonSubTypes
{
// MIT License
//
// Copyright (c) 2017 Emmanuel Counasse
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
public class JsonSubtypesConverterBuilder
{
private Type _baseType;
private string _discriminatorProperty;
private readonly NullableDictionary<object, Type> _subTypeMapping = new NullableDictionary<object, Type>();
private bool _serializeDiscriminatorProperty;
private bool _addDiscriminatorFirst;
private Type _fallbackSubtype;
public static JsonSubtypesConverterBuilder Of(Type baseType, string discriminatorProperty)
{
var customConverterBuilder = new JsonSubtypesConverterBuilder
{
_baseType = baseType,
_discriminatorProperty = discriminatorProperty
};
return customConverterBuilder;
}
public static JsonSubtypesConverterBuilder Of<T>(string discriminatorProperty)
{
return Of(typeof(T), discriminatorProperty);
}
public JsonSubtypesConverterBuilder SerializeDiscriminatorProperty()
{
return SerializeDiscriminatorProperty(false);
}
public JsonSubtypesConverterBuilder SerializeDiscriminatorProperty(bool addDiscriminatorFirst)
{
_serializeDiscriminatorProperty = true;
_addDiscriminatorFirst = addDiscriminatorFirst;
return this;
}
public JsonSubtypesConverterBuilder RegisterSubtype(Type subtype, object value)
{
_subTypeMapping.Add(value, subtype);
return this;
}
public JsonSubtypesConverterBuilder RegisterSubtype<T>(object value)
{
return RegisterSubtype(typeof(T), value);
}
public JsonSubtypesConverterBuilder SetFallbackSubtype(Type fallbackSubtype)
{
_fallbackSubtype = fallbackSubtype;
return this;
}
public JsonSubtypesConverterBuilder SetFallbackSubtype<T>(object value)
{
return RegisterSubtype(typeof(T), value);
}
public JsonConverter Build()
{
return new JsonSubtypesByDiscriminatorValueConverter(_baseType, _discriminatorProperty, _subTypeMapping, _serializeDiscriminatorProperty, _addDiscriminatorFirst, _fallbackSubtype);
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment