CopyPastor

Detecting plagiarism made easy.

Score: 1; Reported for: Exact paragraph match Open both answers

Possible Plagiarism

Plagiarized on 2020-02-05
by Leo Zhu - MSFT

Original Post

Original - Posted on 2016-01-12
by Denis Pitcher



            
Present in both answers; Present only in the new answer; Present only in the old answer;

you could try to use a custom JSON converter to allow the format to be deserialized correctly.
class DateFixingConverter : JsonConverter { public override bool CanConvert(Type objectType) { return (objectType == typeof(DateTime) || objectType == typeof(DateTime?)); }
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { string rawDate = (string)reader.Value; DateTime date; // First try to parse the date string as is (in case it is correctly formatted) if (DateTime.TryParse(rawDate, out date)) { return date; } // If not, see if the string matches the known bad format. // If so, replace the ':' with '.' and reparse. if (rawDate.Length > 19 && rawDate[19] == ':') { rawDate = rawDate.Substring(0, 19) + '.' + rawDate.Substring(20); if (DateTime.TryParse(rawDate, out date)) { return date; } }
// It's not a date after all, so just return the default value if (objectType == typeof(DateTime?)) return null;
return DateTime.MinValue; }
public override bool CanWrite { get { return false; } }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { throw new NotImplementedException(); } } then use like :
JsonSerializerSettings settings = new JsonSerializerSettings { Converters = new List<JsonConverter> { new DateFixingConverter() }, DateParseHandling = DateParseHandling.None };
var result = JsonConvert.DeserializeObject<Logis[]>(returnJson,settings );
As another variation on Totem's known type solution, you can use reflection to create a generic type resolver to avoid the need to use known type attributes.
This uses a technique similar to [Juval Lowy's GenericResolver][1] for WCF.
As long as your base class is abstract or an interface, the known types will be automatically determined rather than having to be decorated with known type attributes.
In my own case I opted to use a $type property to designate type in my json object rather than try to determine it from the properties, though you could borrow from other solutions here to use property based determination.
public class JsonKnownTypeConverter : JsonConverter { public IEnumerable<Type> KnownTypes { get; set; }
public JsonKnownTypeConverter() : this(ReflectTypes()) { } public JsonKnownTypeConverter(IEnumerable<Type> knownTypes) { KnownTypes = knownTypes; }
protected object Create(Type objectType, JObject jObject) { if (jObject["$type"] != null) { string typeName = jObject["$type"].ToString(); return Activator.CreateInstance(KnownTypes.First(x => typeName == x.Name)); } else { return Activator.CreateInstance(objectType); } throw new InvalidOperationException("No supported type"); }
public override bool CanConvert(Type objectType) { if (KnownTypes == null) return false;
return (objectType.IsInterface || objectType.IsAbstract) && KnownTypes.Any(objectType.IsAssignableFrom); }
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { // Load JObject from stream JObject jObject = JObject.Load(reader);
// Create target object based on JObject var target = Create(objectType, jObject); // Populate the object properties serializer.Populate(jObject.CreateReader(), target); return target; }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { throw new NotImplementedException(); }
//Static helpers static Assembly CallingAssembly = Assembly.GetCallingAssembly();
static Type[] ReflectTypes() { List<Type> types = new List<Type>(); var referencedAssemblies = Assembly.GetExecutingAssembly().GetReferencedAssemblies(); foreach (var assemblyName in referencedAssemblies) { Assembly assembly = Assembly.Load(assemblyName); Type[] typesInReferencedAssembly = GetTypes(assembly); types.AddRange(typesInReferencedAssembly); } return types.ToArray(); }
static Type[] GetTypes(Assembly assembly, bool publicOnly = true) { Type[] allTypes = assembly.GetTypes();
List<Type> types = new List<Type>();
foreach (Type type in allTypes) { if (type.IsEnum == false && type.IsInterface == false && type.IsGenericTypeDefinition == false) { if (publicOnly == true && type.IsPublic == false) { if (type.IsNested == false) { continue; } if (type.IsNestedPrivate == true) { continue; } } types.Add(type); } } return types.ToArray(); }
It can then be installed as a formatter
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.Converters.Add(new JsonKnownTypeConverter());

[1]: https://msdn.microsoft.com/en-us/magazine/gg598929.aspx?f=255&MSPPError=-2147217396

        
Present in both answers; Present only in the new answer; Present only in the old answer;