Можно ли сериализовать производные свойства членов списка в System.Text. Json? - PullRequest
2 голосов
/ 05 января 2020

В соответствии с документацией System.Text.Json:

Для сериализации свойств производного типа используйте один из следующих подходов:

  • (...)
  • Объявить сериализованный объект как object.

К сожалению, как я только что выяснил, это не позволяет сериализовать производные свойства членов списка. Рассмотрим следующие классы DTO:

public abstract class GameUpdate
{
    public abstract string Type { get; }
}

public class ConsoleMessage : GameUpdate
{
    public override string Type => "ConsoleMessage";

    public string MessageContent { get; set; }
}

public class HitpointsUpdate : GameUpdate
{
    public override string Type => "HitpointsUpdate";

    public long MonsterID { get; set; }
    public long NewHP { get; set; }
}

Они должны использоваться как List<GameUpdate>. К сожалению, объявление списка для сериализации как object все еще не может сериализовать важные свойства:

var gameUpdates = new List<GameUpdate>
{
    new ConsoleMessage { MessageContent = "Chimzee lost 10 HP!"},
    new HitpointsUpdate { MonsterID = 5, NewHP = 90 }
};
var json = System.Text.Json.JsonSerializer.Serialize<object>(gameUpdates);
Console.WriteLine(json);

Это приводит к следующему JSON:

[{"Type":"ConsoleMessage"},{"Type":"HitpointsUpdate"}]

Для сравнения, используя Newtonsoft.Json.JsonConvert.SerializeObject(gameUpdates) дает следующий результат:

[{"Type":"ConsoleMessage","MessageContent":"Chimzee lost 10 HP!"},{"Type":"HitpointsUpdate","MonsterID":5,"NewHP":90}]

Можно ли добиться аналогичных результатов, используя System.Text.Json?

Почему я спрашиваю это: я постоянно пытаюсь разработать браузерную игру в качестве хобби-проекта, и именно так я реализовал взаимодействие сервера с браузером. С выходом Asp. NET Core 3 его документация поощряет переход с Newtonsoft. JSON на System.Text. Json. Прочитав в документации, что сериализация polymorphi c возможна, я удалил код, связанный с Newtonsoft, и начал использовать System.Text. Json, только чтобы узнать, что игра больше не работает.

1 Ответ

3 голосов
/ 05 января 2020

это работает:

var gameUpdates = new List<object>
{
    new ConsoleMessage { MessageContent = "Chimzee lost 10 HP!"},
    new HitpointsUpdate { MonsterID = 5, NewHP = 90 }
};

var json = JsonSerializer.Serialize(gameUpdates);
Console.WriteLine(json);

[{"Type":"ConsoleMessage","MessageContent":"Chimzee lost 10 HP!"},{"Type":"HitpointsUpdate","MonsterID":5,"NewHP":90}]

Примечание: Ваш подход может быть опасным, вы должны сохранить белый список разрешенных типов для повторной десериализации или злоумышленник может внедрить создание своих собственных типов ... Гораздо безопаснее просто сериализовать один тип объекта в одну коллекцию.

Что если злоумышленник внедряет такой код:

" Тип ":" System.Drawing.Bitmap "," Ширина ":" 100000 "," Высота ":" 100000 "

...