Можете ли вы создать экземпляр объекта из JSON в .NET?

Поскольку инициализаторы объектов очень похожи на JSON, и теперь в .NET есть анонимные типы. Было бы здорово иметь возможность взять строку, такую ​​как JSON, и создать анонимный объект, представляющий строку JSON.

Используйте инициализаторы объектов для создания анонимного типа:

var person = new {
    FirstName = "Chris",
    LastName = "Johnson"
};

Было бы здорово, если бы вы могли передать строковое представление кода инициализатора объекта (желательно что-то вроде JSON) для создания экземпляра анонимного типа с этими данными.

Я не знаю, возможно ли это, поскольку C# не является динамическим, а компилятор фактически преобразует инициализатор объекта в d Анонимный ввод в строго типизированный код, который может выполняться. Это объясняется в в этой статье.

Возможно, лучше всего подойдет функция получения JSON и создания с его помощью словаря ключ / значение.

Я знаю, что вы можете сериализовать / десериализовать объект в JSON в .NET, но я ищу способ создать объект, который по сути слабо типизирован, аналогично тому, как работает JavaScript.

Кто-нибудь знает лучшее решение для этого в .NET?

ОБНОВЛЕНИЕ: слишком проясните контекст, почему я спрашиваю об этом ... Я думал о том, как C# может лучше поддерживать JSON на уровне языка (возможно), и я пытался придумать способы, которыми это можно было бы сделать сегодня, для концептуального причины. Итак, я решил разместить это здесь, чтобы начать обсуждение.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
9
0
15 802
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Какое приложение для этого?

Я бы не пошел по этому пути по нескольким причинам.

  • Первый; для создания прозрачного метода, о котором вы говорите, может потребоваться много кода поддержки, использующего отражение и тому подобное.

  • Во-вторых, как вы сказали, C# - это строго типизированный язык, и подобные вещи по какой-то причине были исключены из спецификации языка.

  • В-третьих, накладных расходов на это не стоит. Помните, что веб-страницы (особенно запросы AJAX) должны быть очень быстрыми, иначе это не поможет. Если вы продолжите и потратите 50% на сериализацию ваших объектов между C# и Javascript, у вас возникнет проблема.

Моим решением было бы создать класс, который просто инкапсулирует словарь и принимает строку JSON в качестве аргумента ctor. Затем просто расширите этот класс для каждого типа запроса JSON, который вы хотите обработать. Это будет строго типизированное и более быстрое решение, но с сохранением расширяемости и простоты использования. Обратной стороной является то, что для каждого типа запроса JSON требуется писать больше кода.

:)

Ответ принят как подходящий

Существуют языки для .NET, в которых есть утиная типизация, но это невозможно в C# с использованием Dot.Notation, поскольку C# требует, чтобы все ссылки на элементы разрешались во время компиляции. Если вы хотите использовать Dot.Notation, вам все равно нужно определить класс где-нибудь с необходимыми свойствами и использовать любой метод, который вы хотите создать экземпляр класса из данных JSON. Предварительное определение класса делает имеет такие преимущества, как строгая типизация, поддержка IDE, включая intellisense, и отсутствие необходимости беспокоиться об орфографических ошибках. Вы все еще можете использовать анонимные типы:

 T deserialize<T>(string jsonStr, T obj) { /* ... */}

 var jsonString = "{FirstName='Chris', LastName='Johnson, Other='unused'}";
 var person     = deserialize(jsonString, new {FirstName = "",LastName = ""});
 var x          = person.FirstName; //strongly-typed

+1, грязно, но в настоящее время единственный способ сделать то, что хочет ОП.

user7116 14.10.2008 06:38

Очень хорошо, об этом я и не подумал.

Chris Pietschmann 14.10.2008 07:15

как вы думаете, что ответ будет, поскольку теперь C# поддерживает динамические типы

Shekhar_Pro 05.05.2011 20:17

Вы должны проверить проект JSON.net:

http://james.newtonking.com/pages/json-net.aspx

Вы в основном говорите о способности гидратировать объект из JSON, что и будет. Он не будет работать с анонимными типами, но, возможно, он подойдет вам достаточно близко.

Вы не можете вернуть анонимный тип из метода **, поэтому существование «регидратированного» анонимного типа будет ограничено методом, в котором он регидратирован. Вроде бессмысленно.

** Вы можете вернуть его как объект (который требует отражения для доступа к его свойствам - да) или вы можете «использовать его на примере», что тоже бессмысленно, поскольку требует дополнительных шагов и означает, что вы уже ЗНАЕТЕ, что Тип объекта должен выглядеть так, так почему бы просто не создать объект и не заполнить его в первую очередь?

Я написал относительно короткий метод, который будет анализировать JSON и возвращать словарь имени / значения, доступ к которому можно получить аналогично фактическому объекту в JavaScript.

Вот пример использования метода ниже:

var obj = ParseJsonToDictionary("{FirstName: \"Chris\", \"Address\":{Street:\"My Street\",Number:123}}");

// Access the Address.Number value
object streetNumber = ((Dictionary<string, object>)obj["Address"])["Number"];

И вот код метода ParseJsonToDictionary:

public static Dictionary<string, object> ParseJsonToDictionary(string json)
{
    var d = new Dictionary<string, object>();

    if (json.StartsWith("{"))
    {
        json = json.Remove(0, 1);
        if (json.EndsWith("}"))
            json = json.Substring(0, json.Length - 1);
    }
    json.Trim();

    // Parse out Object Properties from JSON
    while (json.Length > 0)
    {
        var beginProp = json.Substring(0, json.IndexOf(':'));
        json = json.Substring(beginProp.Length);

        var indexOfComma = json.IndexOf(',');
        string endProp;
        if (indexOfComma > -1)
        {
            endProp = json.Substring(0, indexOfComma);
            json = json.Substring(endProp.Length);
        }
        else
        {
            endProp = json;
            json = string.Empty;
        }

        var curlyIndex = endProp.IndexOf('{');
        if (curlyIndex > -1)
        {
            var curlyCount = 1;
            while (endProp.Substring(curlyIndex + 1).IndexOf("{") > -1)
            {
                curlyCount++;
                curlyIndex = endProp.Substring(curlyIndex + 1).IndexOf("{");
            }
            while (curlyCount > 0)
            {
                endProp += json.Substring(0, json.IndexOf('}') + 1);
                json = json.Remove(0, json.IndexOf('}') + 1);
                curlyCount--;
            }
        }

        json = json.Trim();
        if (json.StartsWith(","))
            json = json.Remove(0, 1);
        json.Trim();


        // Individual Property (Name/Value Pair) Is Isolated
        var s = (beginProp + endProp).Trim();


        // Now parse the name/value pair out and put into Dictionary
        var name = s.Substring(0, s.IndexOf(":")).Trim();
        var value = s.Substring(name.Length + 1).Trim();

        if (name.StartsWith("\"") && name.EndsWith("\""))
        {
            name = name.Substring(1, name.Length - 2);
        }

        double valueNumberCheck;
        if (value.StartsWith("\"") && value.StartsWith("\""))
        {
            // String Value
            d.Add(name, value.Substring(1, value.Length - 2));
        }
        else if (value.StartsWith("{") && value.EndsWith("}"))
        {
            // JSON Value
            d.Add(name, ParseJsonToDictionary(value));
        }
        else if (double.TryParse(value, out valueNumberCheck))
        {
            // Numeric Value
            d.Add(name, valueNumberCheck);
        }
        else
            d.Add(name, value);
    }

    return d;
}

Я знаю, что этот метод может быть немного грубым и, вероятно, его можно немного оптимизировать, но это первый черновик, и он просто работает.

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

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