serialization - Jaký je nejlepší způsob zpracování verzí pomocí protokolu JSON?

Translate

Normálně píšu všechny části kódu v C # a při psaní protokolů, které jsou serializovány, používám FastSerializer, který rychle a efektivně serializuje / deserializuje třídy. Je také velmi snadno použitelný a poměrně přímočarý dělat „verzování“, tj. Zpracovávat různé verze serializace. Věc, kterou běžně používám, vypadá takto:

public override void DeserializeOwnedData(SerializationReader reader, object context)
{
    base.DeserializeOwnedData(reader, context);
    byte serializeVersion = reader.ReadByte(); // used to keep what version we are using

    this.CustomerNumber = reader.ReadString();
    this.HomeAddress = reader.ReadString();
    this.ZipCode = reader.ReadString();
    this.HomeCity = reader.ReadString();
    if (serializeVersion > 0)
        this.HomeAddressObj = reader.ReadUInt32();
    if (serializeVersion > 1)
        this.County = reader.ReadString();
    if (serializeVersion > 2)
        this.Muni = reader.ReadString();
    if (serializeVersion > 3)
        this._AvailableCustomers = reader.ReadList<uint>();
}

a

public override void SerializeOwnedData(SerializationWriter writer, object context)
{            
    base.SerializeOwnedData(writer, context);
    byte serializeVersion = 4; 
    writer.Write(serializeVersion);


    writer.Write(CustomerNumber);
    writer.Write(PopulationRegistryNumber);            
    writer.Write(HomeAddress);
    writer.Write(ZipCode);
    writer.Write(HomeCity);
    if (CustomerCards == null)
        CustomerCards = new List<uint>();            
    writer.Write(CustomerCards);
    writer.Write(HomeAddressObj);

    writer.Write(County);

    // v 2
    writer.Write(Muni);

    // v 4
    if (_AvailableCustomers == null)
        _AvailableCustomers = new List<uint>();
    writer.Write(_AvailableCustomers);
}

Je tedy snadné přidávat nové věci nebo úplně změnit serializaci, pokud se tak rozhodnete.

Nyní však chci použít JSON z důvodů, které zde nejsou relevantní =) Aktuálně používámDataContractJsonSerializera teď hledám způsob, jak mít stejnou flexibilitu, kterou používám výše uvedený FastSerializer.

Otázka tedy zní; jaký je nejlepší způsob, jak vytvořit protokol / serializaci JSON a být schopen podrobně popsat serializaci tak, abych neporušil serializaci jen proto, že jiný stroj ještě neaktualizoval jejich verzi?

This question and all comments follow the "Attribution Required."

Všechny odpovědi

Translate

Klíčem k verzování JSON je vždy přidat nové vlastnosti a nikdy neodstraňovat ani nepřejmenovávat existující vlastnosti. To je podobné jakojak vyrovnávací paměti protokolů zpracovávají správu verzí.

Například pokud jste začali s následujícím JSON:

{
  "version": "1.0",
  "foo": true
}

A chcete vlastnost „foo“ přejmenovat na „bar“, nejen ji přejmenujte. Místo toho přidejte novou vlastnost:

{
  "version": "1.1",
  "foo": true,
  "bar": true
}

Protože nikdy neodstraňujete vlastnosti, klienti založené na starších verzích budou i nadále fungovat. Nevýhodou této metody je, že JSON se může časem nafouknout a musíte pokračovat v údržbě starých vlastností.

Je také důležité jasně definovat „okrajové“ případy pro vaše klienty. Předpokládejme, že máte vlastnost pole s názvem „fooList“. Vlastnost "fooList" může mít následující možné hodnoty: neexistuje / nedefinováno (vlastnost není fyzicky přítomna v objektu JSON, nebo existuje a je nastavena na "nedefinováno"), null, prázdný seznam nebo seznam s jedna nebo více hodnot. Je důležité, aby klienti pochopili, jak se chovat, zejména v nedefinovaných / null / prázdných případech.

Také bych doporučil přečíst si, jaksémantické verzefunguje. Pokud do čísel verzí zavedete sémantické schéma verzí, lze zpětně kompatibilní změny provést na hranici vedlejší verze, zatímco prolomení změn lze provést na hranici hlavní verze (klienti i servery by se museli shodnout na stejné hlavní verzi) ). I když to není vlastnost samotného JSON, je to užitečné pro komunikaci typů změn, které by měl klient očekávat při změně verze.

Zdroj
Translate

Google založený na Javěknihovna gsonmá vynikající podporu verzí pro json. Mohlo by to být velmi užitečné, pokud uvažujete o cestě java.

Existuje pěkný a snadný návodtady.

Zdroj
Translate

Nepoužívejte DataContractJsonSerializer, jak název napovídá, objekty, které jsou zpracovávány prostřednictvím této třídy, budou muset:

a) Buďte označeni atributy [DataContract] a [DataMember].

b) Být přísně v souladu s definovanou „Smlouvou“, tj. nic méně a nic víc, než je definováno. Jakékoli další nebo chybějící [DataMember] způsobí deserializaci, která vyvolá výjimku.

Pokud chcete být dostatečně flexibilní, použijte JavaScriptSerializer, pokud chcete použít levnou možnost ... nebo použijte tuto knihovnu:

http://json.codeplex.com/

Tím získáte dostatečnou kontrolu nad vaší serializací JSON.

Představte si, že máte objekt v jeho počátcích.

public class Customer
{ 
    public string Name;

    public string LastName;
}

Po serializaci to bude vypadat takto:

{Jméno: „John“, příjmení: „Doe“}

Pokud změníte definici objektu tak, aby přidávala / odebírala pole. Deserializace proběhne hladce, pokud použijete například JavaScriptSerializer.

public class Customer
{ 
    public string Name;

    public string LastName;

    public int Age;
}

Pokud se pokusíte de-serializovat poslední json na tuto novou třídu, nebude vyvolána žádná chyba. Jde o to, že vaše nová pole budou nastavena na výchozí hodnoty. V tomto příkladu: „Věk“ bude nastaven na nulu.

Ve svých vlastních konvencích můžete zahrnout pole přítomné ve všech vašich objektech, které obsahuje číslo verze. V tomto případě poznáte rozdíl mezi prázdným polem nebo nekonzistencí verze.

Takže řekněme: Máte třídu Customer v1 serializovanou:

{ Version: 1, LastName: "Doe", Name: "John" }

Chcete deserializovat na instanci Customer v2, budete mít:

{ Version: 1, LastName: "Doe", Name: "John", Age: 0}

Nějak můžete zjistit, která pole ve vašem objektu jsou nějak spolehlivá a co ne. V tomto případě víte, že vaše instance objektu v2 pochází z instance objektu v1, takže pole Age by nemělo být důvěryhodné.

Mám na paměti, že byste měli použít také vlastní atribut, např. „MinVersion“, a každé pole označit minimálním podporovaným číslem verze, abyste dostali něco jako toto:

public class Customer
{ 
    [MinVersion(1)]
    public int Version;

    [MinVersion(1)]
    public string Name;

    [MinVersion(1)]
    public string LastName;

    [MinVersion(2)]
    public int Age;
}

Později můžete přistupovat k těmto metadatům a dělat s nimi vše, co budete potřebovat.

Zdroj
Translate

Nezáleží na tom, jaký serializační protokol používáte, techniky verzí API jsou obecně stejné.

Obecně potřebujete:

  1. způsob, jak spotřebitel komunikuje s producentem verzi API, kterou přijímá (i když to není vždy možné)
  2. způsob, jak může výrobce vložit informace o verzi do serializovaných dat
  3. zpětně kompatibilní strategie pro zpracování neznámých polí

Ve webovém rozhraní API je obecně verze API, kterou spotřebitel přijímá, vložena do hlavičky Přijmout (napřAccept: application/vnd.myapp-v1+json application/vnd.myapp-v2+jsonznamená, že spotřebitel může zpracovávat buď verzi 1 a verzi 2 vašeho API), nebo méně často v adrese URL (napřhttps://api.twitter.com/1/statuses/user_timeline.json). Toto se obecně používá pro hlavní verze (tj. Zpětně nekompatibilní změny). Pokud server a klient nemají odpovídající hlavičku Accept, pak komunikace selže (nebo probíhá v rámci nejlepšího úsilí nebo v nouzovém stavu výchozího výchozího protokolu, v závislosti na povaze aplikace).

Producent poté vygeneruje serializovaná data v jedné z požadovaných verzí a poté vloží tuto verzi informací do serializovaných dat (např. Jako pole s názvemversion). Spotřebitel by měl použít informace o verzi vložené v datech k určení, jak analyzovat serializovaná data. Informace o verzi v datech by také měly obsahovat vedlejší verzi (tj. Pro zpětně kompatibilní změny), obecně by spotřebitelé měli být schopni ignorovat informace o vedlejší verzi a stále správně zpracovávat data, i když porozumění vedlejší verzi může klientovi umožnit další předpoklady o jak by měly být údaje zpracovány.

Běžnou strategií pro zpracování neznámých polí je to, jak jsou analyzovány HTML a CSS. Když spotřebitel uvidí neznámá pole, měl by je ignorovat, a když v datech chybí pole, které klient očekává, mělo by použít výchozí hodnotu; v závislosti na povaze komunikace můžete také určit některá pole, která jsou povinná (tj. chybějící pole se považují za závažnou chybu). Pole přidaná v menších verzích by měla být vždy volitelným polem; vedlejší verze může přidávat volitelná pole nebo měnit sémantická pole, pokud je zpětně kompatibilní, zatímco hlavní verze může mazat pole nebo přidávat povinná pole nebo měnit sémantická pole zpětně nekompatibilním způsobem.

V rozšiřitelném formátu serializace (jako JSON nebo XML) by data měla být popisná, jinými slovy, názvy polí by měly být vždy uloženy společně s daty; neměli byste se spoléhat na to, že konkrétní data jsou k dispozici na konkrétních pozicích.

Zdroj
Leave a Reply
You must be logged in to post a answer.
O autorovi
Ted