Как сериализовать только определенные свойства объекта - PullRequest
5 голосов
/ 04 июня 2009

Учитывая такой объект:

Foo foo = new Foo
{
    A = "a",
    B = "b",
    C = "c",
    D = "d"
};

Как я могу сериализовать и десериализовать только определенные свойства (например, A и D).

Original: 
  { A = "a", B = "b", C = "c", D = "d" }

Serialized:
  { A = "a", D = "d" }

Deserialized:
  { A = "a", B = null, C = null, D = "d" }

Я написал код с использованием JavaScriptSerializer из System.Web.Extensions.dll:

public string Serialize<T>(T obj, Func<T, object> filter)
{
    return new JavaScriptSerializer().Serialize(filter(obj));
}

public T Deserialize<T>(string input)
{
    return new JavaScriptSerializer().Deserialize<T>(input);
}

void Test()
{
    var filter = new Func<Foo, object>(o => new { o.A, o.D });

    string serialized = Serialize(foo, filter);
    // {"A":"a","D":"d"}

    Foo deserialized = Deserialize<Foo>(serialized);
    // { A = "a", B = null, C = null, D = "d" }
}

Но я бы хотел, чтобы десериализатор работал немного по-другому:

Foo output = new Foo
{
    A = "1",
    B = "2",
    C = "3",
    D = "4"
};

Deserialize(output, serialized);
// { A = "a", B = "2", C = "3", D = "d" }

Есть идеи?

Кроме того, может быть, есть какие-то лучшие или существующие альтернативы?

EDIT:

Было несколько предложений использовать атрибуты для указания сериализуемых полей. Я ищу более динамичное решение. Так что я могу сериализовать A, B и в следующий раз C, D.

РЕДАКТИРОВАТЬ 2:

Подойдут любые решения для сериализации (JSON, XML, Binary, Yaml, ...).

Ответы [ 4 ]

24 голосов
/ 04 июня 2009

Довольно просто - просто украсьте методы, которые вы хотите игнорировать, с помощью атрибута [ScriptIgnore].

4 голосов
/ 29 января 2010

В прошлом я сам делал нечто подобное с сериализатором Javascript. В моем случае я хотел только сериализовать обнуляемые свойства в объекте, который содержал значение. Я сделал это, используя отражение, проверив свойство для значения и добавив свойство в словарь, например

public static Dictionary<string,object> CollectFilledProperties(object instance)
{
    Dictionary<string,object> filledProperties = new Dictionary<string,object>();
    object data = null;

    PropertyInfo[] properties = instance.GetType().GetProperties();
    foreach (PropertyInfo property in properties)
    {
        data = property.GetValue(instance, null);

        if (IsNullable(property.PropertyType) && data == null)
        {
            // Nullable fields without a value i.e. (still null) are ignored.
            continue;
        }

        // Filled has data.
        filledProperties[property.Name] = data;
    }

    return filledProperties;
}

public static bool IsNullable(Type checkType)
{
    if (checkType.IsGenericType && checkType.GetGenericTypeDefinition() == typeof(Nullable<>))
    {
        // We are a nullable type - yipee.
        return true;
    }
    return false;
}

Тогда вместо сериализации исходного объекта вы передаете словарь, а Боб - ваш дядя.

3 голосов
/ 04 июня 2009

Существуют атрибуты, которые можно применять к классам и / или свойствам, управляющим сериализацией. Атрибуты, управляющие сериализацией .

1 голос
/ 04 июня 2009

А как насчет тега атрибута [NonSerialized()]?

    class Foo  
    {
        field A;

        [NonSerialized()]
        field B;

        [NonSerialized()]
        field C;

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