2013-04-12 3 views
3

У нас есть уже определенные JSON-документы, которые используются в качестве формата хранения в базе данных документов, а также отправляются по служебной шине.Обновление документов JSON с помощью JSON.NET

Эти десериализуются в конкретные классы с использованием JSON.NET. Теперь я хотел бы изменить существующее свойство для хранения дополнительных данных (например, в настоящее время один из моих классов содержит массив строк, но теперь я хотел бы, чтобы он был массивом класса, содержащего строку плюс временную метку).

Однако мне все же нужно десериализовать старый формат документа. Есть ли способ, возможно, с пользовательским JsonConverter, чтобы легко конвертировать в новый формат документа, когда приходит старый? При сериализации я хочу, чтобы все документы сохранялись в новом формате.

Так как я просил добавить технические детали, вот надуманный пример для обсуждения:

public class Document 
{ 
    public string[] Array { get; set; } 
} 

Это получает повышен в:

public class Document 
{ 
    public class Entry 
    { 
     public string Value { get; set; } 
     public DateTime Timestamp { get; set; } 
    } 

    public Entry[] Array { get; set; } 
} 

В этом примере, давайте предположим, что любой старый формат, который входит, должен содержать отметку времени DateTime.UtcNow.

+1

Хотя интересно, вопрос не хватает технических деталей, таких как структура JSON (старый и новый) –

+0

@ AdrianCarneiro Это потому, что это вопрос общего назначения. Это не имеет никакого отношения к конкретной структуре JSON; У меня, должно быть, 4-5 форматов документов, которые необходимо обновить на данный момент. –

+0

Блестящий вопрос. – Jonathan

ответ

0

В текущем примере вы можете использовать CustomCreationConverter для класса Entry. Реализация CustomCreationConverter<Entry>:

public class DocumentEntryCreationConverter : CustomCreationConverter<Document.Entry> 
{ 
    public override Document.Entry Create(Type objectType) 
    { 
     return new Document.Entry(); 
    } 

    public override object ReadJson(
     JsonReader reader, 
     Type objectType, 
     object existingValue, 
     JsonSerializer serializer) 
    { 
     // If this is not an object - looks like an old format 
     // So we need only set a value 
     if (reader.TokenType == JsonToken.String) 
     { 
      Document.Entry entry = this.Create(objectType); 
      entry.Value = reader.Value as string; 
      return entry; 
     } 
     else 
     { 
      // This is new format, we can recognise it as an object 
      Debug.Assert(
       reader.TokenType == JsonToken.StartObject, 
       "reader.TokenType == JsonToken.StartObject"); 
      return base.ReadJson(reader, objectType, existingValue, serializer); 
     } 
    } 
} 

И это, как вы можете применить его для входа класса:

public class Document 
{ 
    [JsonConverter(typeof(DocumentEntryCreationConverter))] 
    public class Entry 
    { 
     public string Value { get; set; } 
     public DateTime Timestamp { get; set; } 
    } 

    public Entry[] Array { get; set; } 
} 
+1

Интересные концепции. Со всем этим новым материалом NoSQL это выглядит как классный способ справиться с определенным изменением, если вы думаете об этом раньше времени ... просто нужно каким-то образом придумать тег формата документа из get-go, чтобы что, поскольку у вас есть старые документы с 3 изменений назад, вы можете обновить их без видимых на вид. –

+0

Если бы я захотел начать тегировать документы для номера версии, мог бы я сделать это в корневом классе 'Document' (а не во внутреннем классе' Entry'), а затем получить номер этой версии из конвертера, который работает на ' Entry'? –

+0

Я не знаю, как получить доступ к корневому объекту из 'CustomCreationConverter'. Это мое предложение для вашего случая (a) Удалить атрибут 'CustomCreationConverter' (b) Использовать' JsonTextReader' в строке JSON для чтения первого объекта JSON, который поможет вам найти версию ответа. Например, '{'v': 2, 'document': {...}}'. (c) Прочитайте значение 'document', как обычно, с' JsonConvert.Deserialize', но с преобразователями: 'JsonConvert.Deserialize (jsonDocument, новый DocumentEntryCreationConverter (версия))'. – outcoldman

Смежные вопросы