private object DeserializeObject(JObject jsonObj, Metadata.Entity entity) { if (jsonObj == null) { throw new SerializationException("Object type expected"); } object instance = Activator.CreateInstance(entity.Type); var handled = new HashSet <string>(StringComparer.InvariantCultureIgnoreCase); foreach (var prop in jsonObj.Properties()) { if (entity.Properties.TryGetValue(prop.Name, out Metadata.Property propMeta)) { object value = Deserialize(prop.Value, propMeta.PropertyType); propMeta.PropertyInfo.SetValue(instance, value); handled.Add(prop.Name); } } // Check IsRequired var missing = entity.Properties.Values.Where(it => it.IsRequired && !handled.Contains(it.Name)).ToList(); if (missing.Any()) { string props = (missing.Count == 1 ? "property " : "properties ") + String.Join(", ", missing.Select(it => it.Name)); throw new SerializationException($"Missing required {props} on {entity.Name}"); } return(instance); }
private JToken SerializeEntity(object value, Metadata.Entity entity, Metadata.TypeInfo typeInfo) { var jObject = new JObject(); // Different type: this should be a derived type Type realType = value.GetType(); var allProps = entity.Properties; if (realType != typeInfo.Type) { allProps = new Dictionary <string, Metadata.Property>(); if (!typeInfo.Type.IsAssignableFrom(realType)) { throw new SerializationException($"Type mismatch: {realType.Name} is not a {typeInfo.Type}"); } entity = metadata.Entities.Values.FirstOrDefault(it => it.Type == realType); if (entity == null) { throw new SerializationException($"Type {realType.Name} is not supported in this version ({metadata.CurVersion})"); } jObject["$type"] = entity.Name; // Get all properties of base and derived types do { foreach (var pair in entity.Properties) { allProps[pair.Key] = pair.Value; } entity = entity.Parent; }while (entity != null); } foreach (var propMeta in allProps.Values) { object propValue = propMeta.PropertyInfo.GetValue(value, null); if (!propMeta.IsOptional || !IsDefaultValue(propValue, propMeta.PropertyInfo.PropertyType)) { JToken token = Serialize(propValue, propMeta.PropertyType); jObject[propMeta.Name] = token; } } return(jObject); }