NewtonSoft Json.Net условная сериализация объекта - PullRequest
0 голосов
/ 14 декабря 2018

У меня вопрос по поводу сериализации NewtonSoft Json.Net.Я искал вокруг, но не смог найти решение.В SO есть некоторые вопросы, которые напоминают этот по названию, но ни один не представляет этот сценарий.

Мне нужно предотвратить сериализацию определенных объектов при определенных условиях.

Пример: данныйэтот класс:

class A
{
    B b;
}

Мы можем предотвратить сериализацию B, написав:

class A
{
    B b;
    public bool ShouldSerializeb()
    {
        return false; //validate the condition you want.
    }
}

Но если у нас есть несколько B, нам придётся написать функцию для каждого:

class A
{
    B b;
    B bb;
    B bbb;
    public bool ShouldSerializeb()
    {
        return false; //validate the condition you want.
    }

    public bool ShouldSerializebb()
    {
        return false; //validate the condition you want.
    }

    public bool ShouldSerializebbb()
    {
        return false; //validate the condition you want.
    } 
}

Существует еще один способ: использовать средство разрешения контракта

public class ShouldSerializeContractResolver : DefaultContractResolver
{
    public new static readonly ShouldSerializeContractResolver Instance 
     = new ShouldSerializeContractResolver();
    protected override JsonProperty CreateProperty(MemberInfo member, 
    MemberSerialization memberSerialization)
    {
        JsonProperty property = base.CreateProperty(member, memberSerialization);
        if (property.PropertyType == typeof(B))
        {
            property.ShouldSerialize =
                instance =>
                {
                    if (instance == null)
                        return false;

                    // The problem is that "instance" here is A and not B
                    // preventing the necessary validation

                    return false; //validate the condition you want.
                };
        }
        return property;
    }
}

Вопросы:

  • Есть ли способ получить "экземпляр«B», чтобы проверить его внутренности?

  • Есть ли способ написать функцию для проверки самого объекта, а не члена? Примерно так:


    class B
    {
        public bool ShouldSerialize()
        {
             return false; //validate the condition you want.
        }
    }

Спасибо (вероятно, я должен опубликовать это на github, но мы так привыкли концентрировать вопросы в SO)

Ответы [ 2 ]

0 голосов
/ 15 декабря 2018

Да, вы можете сделать это в ContractResolver.У вас есть instance (из A), и у вас есть свойство (типа B), поэтому вам просто нужно попросить ValueProvider в свойстве дать вам значение из экземпляра.Это то, что вы ищете.Затем вы можете проверить B, чтобы решить, следует ли сериализовать свойство.

Так, например, если класс B выглядел следующим образом:

class B
{
    public string Name { get; set; }
    [JsonIgnore]
    public bool IsHidden { get; set; }
}

В преобразователе можно решить, что вы хотите сериализовать B только если IsHidden равно false:

protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
    JsonProperty property = base.CreateProperty(member, memberSerialization);
    if (property.PropertyType == typeof(B))
    {
        property.ShouldSerialize = instance =>
        {
            if (instance == null) return false;

            B b = (B)property.ValueProvider.GetValue(instance);

            // validate the condition you want, for example:
            return b != null && !b.IsHidden;
        };
    }
    return property;
}

Вот рабочая демонстрация: https://dotnetfiddle.net/4MbQ0q

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

0 голосов
/ 14 декабря 2018

Не могли бы вы написать два метода для ShouldSerialize?

public bool ShouldSerialize(typeof(B))
{
    return false;
}

или написать оверид в классе B и назвать его классом B: A, а затем

Class B : A {
    public overide bool ShouldSerialize()
    {
        return false;
    }
}

Class A {
    public bool ShouldSerialize(){
        return true;
    }
}

и затем вызвать b.ShouldSerialize ();или bb.ShouldSerialize ();

Стоит попробовать, возможно, неправильно понял вопрос, но эй, о, кто-то другой узнает вовремя.

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