Получение каждого отдельного свойства произвольной формы и его значения, преобразование его в необработанные, читаемые полезные данные JSON

Скажем, я хочу вывести структуру данных JSON заказчику. Эти данные JSON будут:

  1. Иметь произвольную форму (в основном это может быть значение, объект или даже массив)
  2. Быть возвращенным во внешний интерфейс напрямую без сериализации (Frontend - это стек JS, возвращающий полезную нагрузку JSON без сериализации строк, что позволило бы ему явным образом выполнить приведение самостоятельно).

Я искал Stackru и нашел хороший фрагмент от @dbc:

    /// <summary>
    /// Adapted from dbc answer https://stackru.com/a/60997251/3744182
    /// To https://stackru.com/questions/60994574/how-to-extract-all-values-for-all-jsonproperty-objects-with-a-specified-name-fro
    /// 
    /// </summary>
    public static class JsonExtensions
    {
        public static IEnumerable<JsonElement> DescendantPropertyValues(this JsonElement element)
        {
            var query = RecursiveEnumerableExtensions.Traverse(
                    (Name: (string) null, Value: element),
                    t =>
                    {
                        switch (t.Value.ValueKind)
                        {
                            case JsonValueKind.Array:
                                return t.Value.EnumerateArray().Select(i => ((string) null, i));
                            case JsonValueKind.Object:
                                return t.Value.EnumerateObject().Select(p => (p.Name, p.Value));
                            default:
                                return Enumerable.Empty<(string, JsonElement)>();
                        }
                    }, false)
                .Select(t => t.Value);
            return query;
        }
    }

    public static class RecursiveEnumerableExtensions
    {
        // Rewritten from the answer by Eric Lippert https://stackru.com/users/88656/eric-lippert
        // to "Efficient graph traversal with LINQ - eliminating recursion" https://stackru.com/questions/10253161/efficient-graph-traversal-with-linq-eliminating-recursion
        // to ensure items are returned in the order they are encountered.
        public static IEnumerable<T> Traverse<T>(
            T root,
            Func<T, IEnumerable<T>> children, bool includeSelf = true)
        {
            if (includeSelf)
                yield return root;
            var stack = new Stack<IEnumerator<T>>();
            try
            {
                stack.Push(children(root).GetEnumerator());
                while (stack.Count != 0)
                {
                    var enumerator = stack.Peek();
                    if (!enumerator.MoveNext())
                    {
                        stack.Pop();
                        enumerator.Dispose();
                    }
                    else
                    {
                        yield return enumerator.Current;
                        stack.Push(children(enumerator.Current).GetEnumerator());
                    }
                }
            }
            finally
            {
                foreach (var enumerator in stack)
                    enumerator.Dispose();
            }
        }
    }

С помощью этих методов я мог легко вывести любую структуру данных запрашивающей стороне. Но проблема в том, что значения, возвращаемые в каждом свойстве, просто содержатValueKind.

Итак, как нам вместо возврата ValueKind вернуть фактическое свойство (будь то объект, массив и т. Д.)?

Еще проще, если существует метод, который имитирует то, что Serialize() есть, но без включений и всего остального, это будет идеально для внешнего интерфейса, потому что в этом сценарии отсутствует требование внешнего интерфейса для Parse() входящая сериализованная строка, позволяющая ей "преобразовать" самостоятельно.

Текущий поток кода: данные поступают, я настраиваю ICollection с именемconcatPayload (Мне нужно, чтобы это была коллекция, потому что мне нужно обрабатывать другие наборы данных / данные, если поступает больше, а иногда это может быть или не быть JSON. Но если это не JSON, он будет систематически преобразован.)

var jsonDoc = JsonDocument.Parse(args.Data);
    concatPayload.Add(jsonDoc.RootElement.DescendantPropertyValues()
        .Where(v => v.ValueKind.IsPrimitive())
            .Select(v => v.Clone()).ToList());

Я выполняю код, рекомендованный dbc выше.

return Ok(await _api.Dispatch(vm)); // The Dispatch method runs the concatPayload population flow.

Проще говоря,

  1. Я беру источник,

  2. Я обрабатываю его, проверяю, JSON это или нет. Если это так, я сделаю вышеупомянутый синтаксический анализ для проверки. Если нет, я конвертирую его в JSON.

  3. Я прячу его как коллекцию

  4. Я возвращаю всю ViewModel

    открытый класс DispatchViewModel { /// /// Если это всплывает, пользователь, должно быть, сделал что-то плохое /// публичная строка? ErrorReason {получить; задавать; }

        /// <summary>
        /// The raw payload of the object, in JSON.
        /// </summary>
        public ICollection<object> Payload { get; set; }
    }
    

0 ответов

Другие вопросы по тегам