public override MList <T>?Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options, MList <T>?existingValue) { var existingMList = (IMListPrivate <T>?)existingValue; var dic = existingMList == null ? new Dictionary <PrimaryKey, MList <T> .RowIdElement>() : existingMList.InnerList.Where(a => a.RowId.HasValue).ToDictionary(a => a.RowId !.Value, a => a); var newList = new List <MList <T> .RowIdElement>(); var tup = EntityJsonContext.CurrentPropertyRouteAndEntity !.Value; var elementPr = tup.pr.Add("Item"); var rowIdType = GetRowIdTypeFromAttribute(tup.pr); reader.Assert(JsonTokenType.StartArray); reader.Read(); while (reader.TokenType == JsonTokenType.StartObject) { reader.Read(); reader.Assert(JsonTokenType.PropertyName); if (reader.GetString() != "rowId") { throw new JsonException($"member 'rowId' expected in {reader.CurrentState}"); } reader.Read(); var rowIdValue = reader.GetLiteralValue(); reader.Read(); reader.Assert(JsonTokenType.PropertyName); if (reader.GetString() != "element") { throw new JsonException($"member 'element' expected in {reader.CurrentState}"); } reader.Read(); using (EntityJsonConverterFactory.SetPath($"[{newList.Count}].element")) { if (rowIdValue != null && !rowIdValue.Equals(GraphExplorer.DummyRowId.Object)) { var rowId = new PrimaryKey((IComparable)ReflectionTools.ChangeType(rowIdValue, rowIdType) !); var oldValue = dic.TryGetS(rowId); using (EntityJsonContext.SetCurrentPropertyRouteAndEntity((elementPr, tup.mod, rowId))) { if (oldValue == null) { T newValue = (T)converter.Read(ref reader, typeof(T), options) !; newList.Add(new MList <T> .RowIdElement(newValue, rowId, null)); } else { T newValue = converter is JsonConverterWithExisting <T> jcwe ? (T)jcwe.Read(ref reader, typeof(T), options, oldValue.Value.Element !) ! : (T)converter.Read(ref reader, typeof(T), options) !; if (oldValue.Value.Element !.Equals(newValue)) { newList.Add(new MList <T> .RowIdElement(newValue, rowId, oldValue.Value.OldIndex)); } else { newList.Add(new MList <T> .RowIdElement(newValue)); } } } }
public override Lite <T>?Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options, Lite <T>?existingValue) { if (reader.TokenType == JsonTokenType.Null) { return(null); } reader.Assert(JsonTokenType.StartObject); string?toString = null; string?idObj = null; string?typeStr = null; Entity?entity = null; reader.Read(); while (reader.TokenType == JsonTokenType.PropertyName) { var propName = reader.GetString(); switch (propName) { case "toStr": reader.Read(); toString = reader.GetString(); break; case "id": { reader.Read(); idObj = reader.TokenType == JsonTokenType.Null ? null : reader.TokenType == JsonTokenType.String ? reader.GetString() : reader.TokenType == JsonTokenType.Number ? reader.GetInt64().ToString() : reader.TokenType == JsonTokenType.True ? true.ToString() : reader.TokenType == JsonTokenType.False ? false.ToString() : throw new UnexpectedValueException(reader.TokenType); break; } case "EntityType": reader.Read(); typeStr = reader.GetString(); break; case "entity": using (EntityJsonConverterFactory.SetPath(".entity")) { reader.Read(); var converter = (JsonConverterWithExisting <Entity>)options.GetConverter(typeof(Entity)); entity = converter.Read(ref reader, typeof(Entity), options, (Entity?)(IEntity?)existingValue?.EntityOrNull); } break; default: throw new JsonException("unexpected property " + propName); } reader.Read(); } reader.Assert(JsonTokenType.EndObject); Type type = TypeLogic.GetType(typeStr !); PrimaryKey?idOrNull = idObj == null ? (PrimaryKey?)null : PrimaryKey.Parse(idObj, type); if (entity == null) { return((Lite <T>)Lite.Create(type, idOrNull !.Value, toString !)); } var result = (Lite <T>)entity.ToLiteFat(toString); if (result.EntityType != type) { throw new InvalidOperationException("Types don't match"); } if (result.IdOrNull != idOrNull) { throw new InvalidOperationException("Id's don't match"); } var existing = existingValue as Lite <T>; if (existing.Is(result) && existing !.EntityOrNull == null && result.EntityOrNull != null) { existing.SetEntity((Entity)(IEntity)result.EntityOrNull); return(existing); } return(result); }