public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
                                        JsonSerializer serializer)
        {
            if (reader.TokenType == JsonToken.Null)
            {
                return(null);
            }

            JObject jObject = JObject.Load(reader);
            string  kind    = jObject[nameof(Ust.Kind)]?.ToString() ?? "";

            if (!ReflectionCache.TryGetClassType(kind, out Type type))
            {
                JsonUtils.LogError(Logger, SerializedFile, jObject, $"Unknown UST {nameof(Ust.Kind)} {kind}");
                return(null);
            }

            RootUst rootUst = null;
            Ust     ust;

            if (type == typeof(RootUst))
            {
                TextFile sourceFile     = jObject["SourceCodeFile"]?.ToObject <TextFile>(serializer); // Back compatibility with external serializers
                string   languageString = (string)jObject[nameof(RootUst.Language)] ?? "";
                Enum.TryParse(languageString, out Language language);
                rootUst = new RootUst(sourceFile, language);
                ProcessRootUst(rootUst);

                ust = rootUst;
            }
            else
            {
                ust = (Ust)Activator.CreateInstance(type);
            }

            if (rootAncestors.Count > 0)
            {
                ust.Root = rootAncestors.Peek();
            }
            if (ancestors.Count > 0)
            {
                ust.Parent = ancestors.Peek();
            }

            if (rootUst != null)
            {
                rootAncestors.Push(rootUst);
            }
            ancestors.Push(ust);

            try
            {
                serializer.Populate(jObject.CreateReader(), ust);
            }
            catch (Exception ex)
            {
                Logger.LogError(SerializedFile, jObject, ex);
            }

            JToken textSpanToken = jObject[nameof(Ust.TextSpan)];

            TextSpan[] textSpans;

            if (textSpanToken is JArray textSpanArray)
            {
                textSpans = new TextSpan[textSpanArray.Count];
                for (int i = 0; i < textSpanArray.Count; i++)
                {
                    textSpans[i] = textSpanArray[i].ToObject <TextSpan>(serializer);
                }
            }
            else if (textSpanToken is JToken token)
            {
                textSpans = new [] { token.ToObject <TextSpan>(serializer) };
            }
            else
            {
                textSpans = new TextSpan[0];
            }

            ust.TextSpans = textSpans;

            if (!IgnoreExtraProcess)
            {
                ExtraProcess(ust, jObject, serializer);
            }

            if (rootUst != null)
            {
                rootAncestors.Pop();
            }
            ancestors.Pop();

            return(ust);
        }
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
                                        JsonSerializer serializer)
        {
            if (reader.TokenType == JsonToken.Null)
            {
                return(null);
            }

            JObject jObject = JObject.Load(reader);
            string  kind    = jObject[nameof(Ust.Kind)]?.ToString() ?? "";

            if (!ReflectionCache.TryGetClassType(kind, out Type type))
            {
                JsonUtils.LogError(Logger, JsonFile, jObject, $"Unknown UST {nameof(Ust.Kind)} {kind}");
                return(null);
            }

            RootUst rootUst = null;
            Ust     ust;

            if (type == typeof(RootUst))
            {
                string   languageString = (string)jObject?[nameof(RootUst.Language)] ?? "";
                Language language       = !string.IsNullOrEmpty(languageString)
                    ? languageString.ParseLanguages().FirstOrDefault()
                    : Uncertain.Language;

                rootUst = (RootUst)Activator.CreateInstance(type, null, language);
                ProcessRootUst(rootUst);

                ust = rootUst;
            }
            else
            {
                ust = (Ust)Activator.CreateInstance(type);
            }

            if (rootAncestors.Count > 0)
            {
                ust.Root = rootAncestors.Peek();
            }
            if (ancestors.Count > 0)
            {
                ust.Parent = ancestors.Peek();
            }

            if (rootUst != null)
            {
                rootAncestors.Push(rootUst);
            }
            ancestors.Push(ust);

            List <TextSpan> textSpans =
                jObject[nameof(Ust.TextSpan)]?.ToTextSpans(serializer).ToList() ?? null;

            if (textSpans != null && textSpans.Count > 0)
            {
                if (textSpans.Count == 1)
                {
                    ust.TextSpan = textSpans[0];
                }
                else
                {
                    ust.InitialTextSpans = textSpans;
                    ust.TextSpan         = textSpans.First();
                }
            }

            try
            {
                serializer.Populate(jObject.CreateReader(), ust);
            }
            catch (Exception ex)
            {
                Logger.LogError(JsonFile, jObject, ex);
            }

            if (!IgnoreExtraProcess)
            {
                ExtraProcess(ust, jObject);
            }

            if (rootUst != null)
            {
                rootAncestors.Pop();
            }
            ancestors.Pop();

            return(ust);
        }