Десериализованный объект, отличный от исходного сериализованного объекта - PullRequest
2 голосов
/ 15 марта 2020

Я использую ASP Net Core 2.2

Я разделяю этот динамический c объект

var stuff1 = new
{
    Name = "John",
    Surname = "Smith",
    Addresses = new[] {
new { City = "New York", State = "NY"},
new { City = "Milano", State = "IT" }
};
var stuff1Serialized = JsonConvert.SerializeObject(stuff1)

Это сериализованный объект:

{"Name":"John","Surname":"Smith"}

Теперь я получил эту строку и десериализовал ее

dynamic stuff1Deserialized = JsonConvert.DeserializeObject(stuff1Serialized);

Я ожидаю, что sutff1 и stuff1Deseralized имеют одинаковую структуру, но они разные, почему?

В окне Immediate:

stuff1.name
"Jhon"

stuff1Deserialized.Name
{John}
    First: '((Newtonsoft.Json.Linq.JToken)stuff1Deserialized.Name).First' threw an exception of type 'System.InvalidOperationException'
    HasValues: false
    Last: '((Newtonsoft.Json.Linq.JToken)stuff1Deserialized.Name).Last' threw an exception of type 'System.InvalidOperationException'
    Next: null
    Parent: {"Name": "John"}
    Path: "Name"
    Previous: null
    Root: {{
  "Name": "John",
  "Surname": "Smith"
}}
    Type: String
    Value: "John"
    Results View: Expanding the Results View will enumerate the IEnumerable

Я использую объект с этим простым шаблоном DotLiquid:

Hello {{Name}} {{Surname}}. Number of Addresses: {{Addresses.size}} - {{Addresses[0].City}} - {{Addresses[1].City}}

С объектом stuff1 я получил ожидаемый результат:

Hello John Smith. Number of Addresses: 2 - New York - Milano

С объектом stuff1Deserialized я получил этот результат:

Hello John Smith. Number of Addresses: 2 - -

1 Ответ

3 голосов
/ 15 марта 2020

Обновление согласно комментарию

Я нашел один способ сделать это:

1 - объект динамический c образец:

dynamic dynamicStuff = new
{
    Name = "John",
    Surname = "Smith",
    Obj = new { City = "New York", State = "NY" },// i add this to test object
    Addresses = new[]
    {
        new { City = "New York", State = "NY"},
        new { City = "Milano", State = "IT" }
    }
};

2 - Сериализация и десериализация для создания динамического c объекта:

dynamic dynamicStuffDeSerialized = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(dynamicStuff));

3 - Преобразование dynamic объекта в JObject и построение Dictionary Of (string, object) путем преобразования JObject в Dictionary:

Dictionary<string, object> keyValuePairs = ConvertJObject(JObject.FromObject(dynamicStuffDeSerialized));

private static Dictionary<string, object> ConvertJObject(JObject jObject)
{
    Dictionary<string, object> keyValuePairs = new Dictionary<string, object>();
    foreach (var property in jObject)
    {
        if (property.Value.Type == JTokenType.Array)
            keyValuePairs.Add(property.Key, ConvertJArray(property.Value.Select(o=>(JObject)o)));

        else if (property.Value.Type == JTokenType.Object)
            keyValuePairs.Add(property.Key, ConvertJObject((JObject)property.Value));

        else
            keyValuePairs.Add(property.Key, property.Value.ToString());
    }

    return keyValuePairs;
}

private static List<Dictionary<string, object>> ConvertJArray(IEnumerable<JObject> jObjects)
{
    return jObjects.Select(o => ConvertJObject(o)).ToList();
}

Обратите внимание, что вы можете использовать ToObject для преобразования JObject в Dictionary, но он конвертирует только простое значение, а не объект или массив, например:

JObject jObject = JObject.FromObject(dynamicStuffDeSerialized);
Dictionary<string, object> dict = jObject.ToObject<Dictionary<string, object>>();

4 - используйте Hash.FromDictionary, а не Hash.FromAnonymousObject:

Template templatedynamicStuff = Template.Parse("Hello {{Name}} {{Surname}} City in Object {{Obj.City}}. Number of Addresses: {{Addresses.size}} - {{Addresses[0].City}} - {{Addresses[1].City}}");
string result = templatedynamicStuff.Render(Hash.FromDictionary(keyValuePairs));

Обратите внимание, что я изменил template, добавив City in Object {{Obj.City}}

5 - ТЕСТ

Console.WriteLine(result);

6 - РЕЗУЛЬТАТЫ :

Hello John Smith City in Object New York. Number of Addresses: 2 - New York - Milano

Старые ответы

Согласно newtonsoft документация. Вы можете использовать DeserializeAnonymousType вместо DeserializeObject для десериализации Анонимного объекта. но DeserializeAnonymousType нужен definition из анонимный тип Чтобы получить тот же объект .

Как и в следующем коде:

var stuff1 = new
{
    Name = "John",
    Surname = "Smith"
};

var stuff1Serialized = JsonConvert.SerializeObject(stuff1);

var definition = new { Name = "", Surname = "" };
dynamic stuff1Deserialized = JsonConvert.DeserializeAnonymousType(stuff1Serialized, definition);

Обновление согласно комментарию

Вы можете использовать JObject или ExpandoObject для получения свойств имена и значения , например, следующий код:

dynamic stuff1 = new
{
    Name = "John",
    Surname = "Smith"
};

var stuff1Serialized = JsonConvert.SerializeObject(stuff1);

dynamic stuff1DeSerialized1 = JsonConvert.DeserializeObject(stuff1Serialized);

foreach (JProperty property in JObject.FromObject(stuff1DeSerialized1))
{
    Console.WriteLine($"Key:{property.Name}, Value:{property.Value}");
}

ExpandoObject stuff1DeSerialized2 = JsonConvert.DeserializeObject<ExpandoObject>(stuff1Serialized, new ExpandoObjectConverter());

foreach(KeyValuePair<string, object> keyValue in stuff1DeSerialized2.ToList())
{
    Console.WriteLine($"Key:{keyValue.Key}, Value:{keyValue.Value}");
}

Я надеюсь найти другое решение и поделиться им с вами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...