• No results found

Implementering av schema för YAML och JSON i .NET

N/A
N/A
Protected

Academic year: 2021

Share "Implementering av schema för YAML och JSON i .NET"

Copied!
41
0
0

Loading.... (view fulltext now)

Full text

(1)

Beteckning:________________

Institutionen för matematik, natur- och datavetenskap

Implementering av schema för YAML och JSON i .NET

Robert Siirilä Oktober 2008

Examensarbete, 15 högskolepoäng, C Datavetenskap

Examinator/handledare: Fredrik Bökman

Medbedömare: Anders Jackson

(2)

Implementering av schema för YAML och JSON i .NET

av Robert Siirilä

Institutionen för matematik, natur- och datavetenskap Högskolan i Gävle

S-801 76 Gävle, Sweden

Email:

robert.siirila@lm.se

Abstrakt

Genom att använda scheman till textfiler som ska matas in ett system, kan textfilerna direkt översättas till systemets interna datastrukturer. Scheman kan också användas för att kontrollera att inte felaktiga värden matas in i systemet. För enklare textfiler som YAML och JSON är det ovanligt med format för att definiera scheman. Det vanligaste schema-formatet för YAML i nuläget är Kwalify, men det finns inte för Microsofts .NET-ramverk. Lösningen är att implementera Kwalify på .NET.

Implementationen benämns Nkwalify. För verifiering av implementeringen används systemdatabasen i Lantmäteriets nya miljö för kartproduktion. Implementeringen jämförs med Xmlserializer, som har delvis samma användningsområde.

Xmlserializer ingår som standard i .NET. Prestandatester visar att vid mycket stora datamängder är Xmlserializer upp till fem gånger snabbare på att ladda in data.

Nkwalify stödjer dock fler datatyper och mer komplicerade datastrukturer än Xmlserializer samt matar ut data minst fem gånger snabbare. Nkwalify är lämplig för snabb och enkel överföring av komplexa data och för kontroll av inmatade värden. Det behövs ytterligare utveckling och tester för att Nkwalify ska vara produktionsklart.

(3)

Innehåll

1 Inledning...3

1.1 Problem...3

1.2 Syfte...4

1.3 Frågeställningar...5

2 Bakgrund ...6

2.1 Begrepp...6

2.2 Lantmäteriets insamlingsenhet och dess system för kartproduktion...10

2.3 Kwalify och YAML jämfört med XMLSerializer...11

2.4 Andra valideringsformat för YAML och JSON...13

2.5 Andra implementationer av YAML för CLI...14

3 Krav...16

3.1 YAML...16

3.2 Kwalify...16

3.3 Ladda och dumpa klasser och objekt...16

3.4 Nhibernate...16

4 Konstruktion...17

4.1 Loader – Laddning...17

4.2 Dumper - Dumpning...17

5 Implementering...18

5.1 Verktyg...18

5.2 Implementering...19

6 Test...20

6.1 Enhetstester...20

6.2 Jämförande körningar med Parser, Serializer, Representer och Constructor...20

6.3 Dumpa vektorer...21

6.4 Jämförande prestandatester med Xmlserializer...21

6.5 Utökning av valideraren med egna regler...22

6.6 Dumpa produktmodeller...23

7 Diskussion...24

7.1 Formatet Kwalify...24

7.2 Problem med implementationen Nkwalify...24

7.3 Önskemål för implementationen Nkwalify...25

8 Slutsatser...26

8.1 Frågeställningar...26

8.2 Förväntat resultat...27

8.3 Uppfyllande av kraven...27

9 Referenser...28

Bilaga 1: Ordlista...30

Bilaga 2: Klassträd för Nkwalify...3

(4)

1 Inledning

Det här arbetet undersöker alternativ - och skapar programvara - för att kontrollera att importfiler följer de regler som definierats. För verifiering av programvaran används systeminställningar för Lantmäteriets nya miljö för kartproduktion. För att kunna verifiera resultatet görs import- och exportfunktioner till och från systeminställningar.

Eftersom programvara som importerar och exporterar inställningar samt kontrollerar giltighet är användbart även utanför Lantmäteriet, görs programmet tillgängligt även för andra utvecklare. De delar som inte är unika för Lantmäteriet läggs på en allmänt tillgänglig lagringsplats, varifrån programvaran inklusive källkod kan hämtas.

1.1 Problem

I dagsläget finns ingen möjlighet att spara systeminställningar i filer (serialisera) och ladda inställningarna från de sparade filerna (deserialisera) i Lantmäteriets nya miljö för kartproduktion. Det finns formulär för inställningar. Systemadministratörer vill kunna spara inställningar, ladda inställningarna till andra miljöer och eventuellt skapa automatiserade rutiner för att bearbeta inställningar. Då fungerar varken formulär eller binära format.

INI-filer är det traditionella sättet att spara inställningar. INI-filer räcker inte till för att beskriva komplicerade datastrukturer. XML har blivit ett allt populärare format, även för inställningar. JSON följt av YAML är den mest och näst mest använda alternativa formaten till XML. YAML är inriktat mot att vara ett format för inställningsfiler och JSON är inriktat mot kommunikation mellan program och datorer.

En stor fördel med XML är dess schemaformat för att beskriva strukturen i XML-filer. Figur 1 ger exempel på INI, JSON, YAML och XML som alla har samma data strukturerat ungefär likadant.

INI [sektion]

nyckel=värde [sektion2]

nyckel2=42 JSON

{"sektion": {"nyckel": "värde"}, "sektion2": {"nyckel2": 42 }}

YAML sektion:

nyckel: värde sektion2:

nyckel2: 42 XML

<rot>

<sektion nyckel="värde"/>

<sektion2 nyckel2="42"/>

</rot>

Figur 1. Exempel på INI, JSON, YAML och XML.

(5)

YAML och JSON är serialiseringsformat som delar logisk struktur, så samma verktyg kan användas för båda formaten [1] . Strukturen efterliknar de strukturer som finns för de vanligaste programmeringsspråken. Översättningen mellan programspråkens struktur och YAML och JSON blir därför enkel. Det krävs inga mellanliggande översättningsmodeller. Det finns ett schemaformat för YAML och JSON, implementerat i Ruby, men inget för .NET.

I rapporten används CLI (Common Language Infrastructure) som samlingsnamn för de olika implementationerna av specifikationen CLI, varav Microsoft .NET Framework är den vanligaste.

Det finns inte automatiska sätt att exportera data från CLI till textfiler i YAML- format. Det går inte heller att importera datastrukturer till CLI från YAML.

1.2 Syfte

Syftet med examensarbetet är att lösa problemet med validering av enkla serialiseringsformat som YAML och JSON för att kunna utöka valideringen mot kompilerade klasser genom reflektion. Valideringen ska ske genom att implementera Kwalify på CLI.

Examensarbetet skall jämföra olika format för serialisering och konfigurering samt undersöka och redovisa valideringsregler, valideringsformat och valideringsmetoder. Undersökningen bildar den teoretiska grunden för att implementera rutiner för beskrivning och validering för automatisk data binding i form av ett klassbibliotek. Vidare skapas en eller flera exempelapplikationer som använder klassbiblioteket.

1.3 Frågeställningar

Går det att fullständigt beskriva klasser och objekt i enkla textfiler (serialisering) och kunna ladda in dessa igen (deserialisering)?

Hur göra med objekt som refererar till sig själva?

Går det att serialisera alla förekommande datatyper?

Går det att serialisera parametriserade typer?

Vad går inte att serialisera och varför?

Jämför serialisering mellan YAML och XML.

Hur sker serialisering i .NET?

Hur utökar man ett schema med ytterligare begränsningar (constraints)? Exempel på intressanta frågeställningar:

Vilka regler finns och vilka används i en stor geografisk databas, utan att blanda in topologiska regler?

T ex domänvärden som ligger databaser, begränsningar som påverkar varandra, finns det regler för fält som ligger i skilda affärsobjekt?

Klassifiering och kategorisering av regler definierade av enskilda programmerare.

Kan ytterligare typer av constraints läggas till Kwalify och i så fall, hur?

(6)

2 Bakgrund

Kapitlet beskriver de begrepp som förekommer i arbetet eller som annars kan vara av betydelse för att förstå arbetet. I kapitlet jämförs också olika serialiserings- och valideringsformat.

2.1 Begrepp

Plain Old CLR/CLI Object (POCO) är instanser av klasser som har följande begränsningar [2]:

ska kunna instansieras utan argument

bara använda get_XX och set_XX för att sätta och hämta attribut

inga externa beroenden

Objekt-relationell mappning (ORM) är en teknik för att översätta data och struktur mellan relationsdataser och objektorienterade system [3]. En databas består av tabeller som i sin tur består av kolumner och rader. Ett objektorienterat system består av klasser med attribut och metoder.

ORM översätter databasens tabeller till klasser, kolumnerna till klassens attribut och raderna bildar instanser av klassen, dvs objekt. Referenser mellan objekt motsvaras av relationer i databasen. Objekten i OR-mappning benämns affärsklasser eller business object. För att mappningen ska fungera krävs att objekten följer POCO- reglerna.

Hibernate för Java och NHibernate för .NET är de vanligaste ramverken för OR- mappning.

Serialisering är en metod att spara undan datastrukturer eller sända strukturerna till en annan dator [4]. Datastrukturerna finns i datorns arbetsminne under körning av ett program. När programmet avslutas, försvinner strukturerna. För att objekten ska finnas efter att programmet avslutats, måste de sparas till hårddisken eller sändas till en annan dator.

Datastrukturen sparas i något lämpligt textformat, men även binära format förekommer. När de serialiserade strukturerna återskapas, dvs laddas in i arbetsminnet under körning av ett program, används begreppet deserialisering. I rapporten används begreppen dumpning för serialisering och laddning för deserialisering.

I standardbiblioteket för en CLI-implementation finns stöd för XML och SOAP samt ett internt binärt format. System.Xml.Serialization.XmlSerializer producerar XML. Klasserna under System.Runtime.Serialization.Formatters producerar binärt format och SOAP.

Validering innebär kontroll av att inmatade värden är inom de restriktioner (constraints) som definierats [5]. Restriktionerna kan programmeras (hårdkodas) och kontrolleras vid inmatningen, eller anges i ett schema-dokument. Exempel på restriktioner:

Kardinalitet. Dvs hur många gånger ett fält får förekomma (+ minst en gång, * noll eller fler gånger, ? noll eller en gång,...)

Rätt datatyp: teckensträng, heltal, flyttal, datum

(7)

Rätt struktur och namn på fält för komplexa typer som lista och tabell

Värdesrestriktioner, sk assert-satser

Teckenmönster, sk patterns, med reguljära uttryck

Reflection används till att titta på och ändra programstrukturen under körning av ett program. Genom reflection kan programmen bearbetas och ändras under körning av programmet. Reflection möjliggör sk metaprogramming, dvs programmering av program som skapar program [6, 7].

static object tag2obj(string assemblyname, SDL.Tag tag, params object [] args) {

object obj = null;

System.Reflection.Assembly A =

System.Reflection.Assembly.Load(assemblyname);

System.Type T = null;

foreach (System.Type t in A.GetExportedTypes()) { if (t.Name == tag.Name) {

T = t;

break;

} }

if (T == null) return null;

obj = args == null ?

System.Activator.CreateInstance(T) :

System.Activator.CreateInstance(T , args, null);

foreach (SDL.Tag childtag in tag.Children) { System.Reflection.PropertyInfo P;

Figur 2. Exempel på reflection i C#.

Exemplet i figur 2 visar hur klassen instansieras och objektet fylls på automatiskt om klassen finns i det angivna biblioteket, sk data binding. Klassen fungerar som schema.

XML (eXtensible Markup Language) är en specifikation för märkspråk i textformat, som har sitt ursprung i SGML (Standard Generalized Markup Language) [8].

Den grundläggande logiska strukturen i en XML instance document är: 1) Element; och 2) Element attribute. I DOM (Document Object Model) definieras ett XML-dokument som ett träd av noder av olika flertal slag. De olika noderna kan ha olika typer och antal av barn-noder [9]:

Document -- Element (högst en), ProcessingInstruction, Comment, DocumentType

DocumentFragment -- Element, ProcessingInstruction, Comment, Text, CDATASection, EntityReference

DocumentType -- inga barn-noder

EntityReference -- Element, ProcessingInstruction, Comment, Text, CDATASection, EntityReference

Element -- Element, Text, Comment, ProcessingInstruction, CDATASection, EntityReference

Attribute -- Text, EntityReference

ProcessingInstruction -- inga barn-noder

(8)

Comment -- inga barn-noder

Text -- inga barn-noder

CDATASection -- inga barn-noder

Entity -- Element, ProcessingInstruction, Comment, Text, CDATASection, EntityReference

Notation -- inga barn-noder

Barn-noderna till en föräldra-nod är inbördes ordnade. Se figur 3 för exempel på XML.

<person

firstName = "John"

lastName" = "Smith">

<address

streetAddress = "21 2nd Street"

city = "New York"

state = "NY"

postalCode = "10021"

/>

<phoneNumbers>

<phoneNumber>212 555-1234</phoneNumber>

<phoneNumber>646 555-4567</phoneNumber>

</phoneNumbers>

</person>

Figur 3. Exempel på XML.

För att t ex hitta första telefonnumret, skrivs följande i något programspråk som stödjer DOM:

XMLDocument.GetElementsByTagName("phoneNumber")[0].GetFirstChild()

JSON (Javascript Object Notation) är ett textformat för att beskriva datastrukturer [10]. Formatet har uppkommit ur behovet att skicka datastrukturer mellan webbklienter och webbservrar. JSON består av sk Object-datastrukturer. I Javascript benämns hashtabeller Object.

{

"firstName": "John", "lastName": "Smith", "address": {

"streetAddress": "21 2nd Street", "city": "New York",

"state": "NY", "postalCode": 10021 },

"phoneNumbers": [ "212 555-1234", "646 555-4567"

] }

Figur 4. Exempel på JSON.

YAML (Yet Another Markup Language alt. YAML Ain't a Markup Language) är utökad JSON och med stöd för radorientering [11]. YAML har uppkommit ur behovet

(9)

att ha ett enkelt med kraftfullt serialiseringsformat för scriptspråk. Formatet togs fram av en grupp XML-utvecklare som ville ha ett enklare XML. Istället för XML skapade de ett helt nytt format.

YAML möjliggör utmatning av data i ett språk och inmatning i ett annat. Stöd för YAML finns för programspråken Perl, PHP, Python, Ruby, Java, Javascript, Ocaml, C++, Objective-C, Lua och Haskell. Till skillnad från XML är YAML framtagen för att vara ett dataserialiseringsformat. YAML används i första hand som ett format för konfigurationsfiler.

firstName: John lastName: Smith address:

city: New York postalCode: 10021 state: NY

streetAddress: 21 2nd Street phoneNumbers:

- 212555-1234 - 646 555-4567

Figur 5. Exempel på YAML.

YAML bygger på standarden Internet Message Format (RFC-2822, [12]) i radformat och JSON (RFC-4627 [13], ECMA-262 [14]) i blockformat. Precis som i JSON utgör nyckeltabell, lista och skalära värden de tre logiska strukturerna som kombineras för att representera strukturerade data.

Engelska JSON YAML CLI Perl Python Ruby Hash object,{} mapping IDictionary hash,# dict,{} hash,{}

List array,[] sequence IList array,@ list,[] array,[]

Scalar value scalar Iconvertible scalar,$

Figur 6. Namn på datastrukturerna nyckeltabell, lista och skalär.

Google använder YAML som konfigurationsformat i sin App Engine [15] och Ruby on Rails, en applikationsplattform för webben, använder YAML som sitt interna format [16].

Kwalify är ett schema-språk för YAML och JSON [17]. Implementationen är gjord i programspråket Ruby. Kwalify-dokument är även giltiga YAML-dokument. Det går att blanda blockorienterat och radorienterat i samma dokument. Figur 7 visar ett validerande schema-dokument till dokumenten i figur 5 och figur 4.

type: map mapping:

"firstName": {required: yes}

"lastName": {required: yes}

"address":

type: map required: no mapping:

"city": {required: yes}

"postalCode": {type: int, required: yes}

"state": {required: yes}

"streetAddress": {required: yes}

"phoneNumbers":

type: seq

(10)

required: no sequence:

- type: str

Figur 7. Exempel på Kwalify.

Kwalify stödjer dokumentstrukturering, har stöd för de vanligaste datatyperna, för patterns med reguljära uttryck och för assert-uttryck. Genom att använda Kwalify kan ett validerat YAML-dokument översättas till en instans av en klass. Kwalify- dokumentet motsvarar då en klass.

I dagsläget finns tre implementationer av Kwalify. Det första är Kwalify för Ruby som är den ursprungliga implementationen. De två andra är gjorda i Perl. Den ena av dem en portning av Ruby-implementationen [18] och den andra är valideras datastrukturerna istället för filen [19].

Common Language Infrastructure (CLI) är en specifikation som är Microsofts motsvarighet till Suns Java med dess virtuella maskin. CLI utgör kärnan i av implementationer som .NET Framework och Mono. Common Language Runtime (CLR) och dotnet är ytterligare namn på Microsofts implementation av CLI med tillägg [20]. CLI liknar Java Virtual Machine (JVM). Både CLI och JVM använder den kompilerade bytekoden som distributionsformat och att båda har omfattande standardbibliotek. Förutom ett huvudspråk har de båda plattformarnarna ett antal alternativa språk som kompileras till bytekod. CLI har även möjligheten att köra scriptspråk med DLR (Dynamic Language Runtime) som IronPython och IronRuby. I dagsläget finns det tjugotal språk som kan kompileras till bytekod och köras på CLI [21]. Boo är ett av dem.

Boo är ett programmeringsspråk som kompileras till CLI. Inspirationen till Boo kommer från de dynamiska språken Python och Ruby [22]. Till skillnad från Python har Boo statiska typer, men typerna behöver inte anges explicit. Examensarbetet är till största del skrivet i Boo.

2.2 Lantmäteriets insamlingsenhet och dess system för kartproduktion

Lantmäteriets insamlingsenhet producerar geografisk information i form av GSD (Geografiska SverigeData), en detaljerad geografisk databas täckande hela landet. Ur GSD produceras papperskartor som Fastighetskartan och Terrängkartan. GSD används också som grund för t ex Eniros kartor på webben. De största kunderna av Lantmäteriets geografiska data är olika statliga verk, länsstyrelser och kommuner.

Ungefär 120 kartritare uppdaterar GSD genom att jämföra flygbilder med den information som finns i GSD. Kommuner, vägverket, banverket, kraftbolag och sjöfartsverket levererar kartdata till Lantmäteriet.

I början av 90-talet utvecklade Lantmäteriet klientapplikationen AUTOKA-PC för kartproduktion. Nu ersätts AUTOKA-PC med ett modernare system från mjukvaruleverantören ESRI. Lantmäteriet utvecklar tillägg till ESRI:s ArcMap för att anpassa programvaran för kartproduktion. Det nya ersättande toposystemet, består av geografisk databas, systemdatabas med inställningar, in- och utcheckningsserver och klient.

Systemdatabasen innehåller inställningar för kartlager, kartprodukter, värdeförråd för text, regler, användare med mera. Klienten kommer åt

(11)

systemdatabasen genom objekt-relationell mappning med Nhibernate. Ett programbibliotek ger objektorienterad åtkomst till systemdatabasen. Varje tabell motsvaras av en klass. Figur 8 ger exempel på radering av en produktmodell (en samling kartlager med regler).

// Öppna session mot databasen.

ISession session = NHibernateTopo.NHSession;

// Hämta produktmodellen med namnet "en modell"

ProduktModell pm = ProduktModell.GetByNamn("en modell", session);

// Om produktmodellen finns, så...

if (pm != null) {

// ..flagga produktmodellen som borttagen..

pm.Delete();

// ..och kör uppdateringsrutin på databasen.

pm.Save();

}

Figur 8. Radering av produktmodell.

2.3 Kwalify och YAML jämfört med XMLSerializer

Det konventionella sättet att serialisera i CLI är med klassen XMLSerializer. Klassen används som referens till Nkwalify. Här jämförs funktionalitet, filformat, vilka datatyper som kan serialiseras mot XMLSerializer. I senare kapitel jämförs prestanda.

class Y {

public Generic.List<int> a;

public Generic.List<ListArray> b;

public int c;

public string d;

public bool e;

public char i;

public X x;

}

class X {

public string x;

}

Figur 9. Klasserna Y och X i C#.

Som exempel används två klasser med några vanligt förekommande datatyper. Figur 9 visar klassen Y som refererar till klassen X. I figur 10 instansieras klasserna.

Y y = new Y();

y.a = new List<int>();

y.a.AddRange({1, 2, 3});

ArrayList bb = new ArrayList();

bb.AddRange({"foo", "bar", "baz"});

y.b = new List<ArrayList>();

y.b.Add(bb);

y.c = 42;

y.d = "hello, world!";

y.e = false;

y.i = 'q';

(12)

y.x = new X();

y.x.x = "Lorem ipsum";

Figur 10. Objekten y och x i C#.

Det enklaste sättet att serialisera i CLI är med XMLSerializer. Till skillnad från SOAP krävs ingen extra programkod eller anpassning av klasserna. Figur 11 visar hur XML- filen ser ut när objekten x och y är serialiserade med XMLSerializer.

<?xml version="1.0" encoding="utf-16"?>

<Y xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<a>

<int>1</int>

<int>2</int>

<int>3</int>

</a>

<b>

<ArrayOfAnyType>

<anyType xsi:type="xsd:string">foo</anyType>

<anyType xsi:type="xsd:string">bar</anyType>

<anyType xsi:type="xsd:string">baz</anyType>

</ArrayOfAnyType>

</b>

<c>42</c>

<d>hello, world!</d>

<e>false</e>

<i>113</i>

<x>

<x>Lorem ipsum</x>

</x>

</Y>

Figur 11. Objekten x och y serialiserade med XMLSerializer.

Jämfört med XML ger YAML en mer korrekt logisk struktur av objekten x och y. De som är vana vid dynamiska språk kan enkelt se strukturen. YAML har ingen redundant information. Se figur 12.

a: [1, 2, 3]

b: [[foo, bar, baz]]

c: 42

d: hello, world!

e: false i: q

x: {x: Lorem ipsum}

Figur 12. Objekten x och y serialiserade med YAML.

En fördel med YAML jämfört med XML är dess stöd för ankare och alias, vilket gör att cykliska strukturer stöds. Ankare och alias leder till att cirkulära referenser kan representeras. Se figur 13 för exempel.

class Z {Z x;}

class Program { void Main() { Z z = new Z();

(13)

z.x = x;

} }

Klassen Z i kwalify:

&id001 type: map class: Z mapping:

x: *id001

Instansen x av klassen X i Yaml:

&id001 x: *id001

Figur 13. Cirkulär referens i C#, Kwalify och YAML.

XMLSerializer stödjer inte cirkulära referenser, hashtabeller och andra mer komplexa datastrukturer.

XMLSerializer blandar data med metadata, vilket gör att det kan vara svårt att ur XML-filen avgöra vad som är data och vad som är strukturbeskrivningar.

Serialiseringen ger inte ren datarepresentation av en instans av en klass.

Kwalify stödjer mer komplicerade datastrukturer. YAML-filerna är jämförelsevis mycket enklare och mindre, med bibehållen strukturinformation. Kombinationen Kwalify som format för att serialiseringar av klasser och YAML för serialiseringar av klassernas instanser ger en tydlig separation mellan data och metadata. Filerna är små och ändamålsenliga.

2.4 Andra valideringsformat för YAML och JSON

Doctrine är ett ramverk för objekt-relationell mappning i PHP, motsvarande Nhibernate för .NET [23]. Istället för att använda XML som i Nhibernate, används YAML som schema-format för att definiera mappningen. Här exempel på definition av en tabell User med en kolumn name av typen string av längd 50 [24].

User:

columns:

name:

type: string(50) default: default name

Figur 14. Exempel på Doctrine-schema.

Tyvärr parsas inte 'string(50)' till 'string' och '50' i YAML, utan det krävs någon form av ytterligare parsning av själva teckensträngen. I Kwalify används YAML-parsern.

Se figur 15 för motsvarande schema i Kwalify.

User:

columns:

name:

type: string length: 50

default: default name

Figur 15. Doctrine-schema i Kwalify.

(14)

Rx är ett schema-språk för YAML och JSON anpassat för datastrukturer. Enligt skaparen av Rx, är Kwalify inte portabelt. Kwalify har referenser i form av ankare och alias, som JSON inte stödjer. Vilket leder till att Kwalify inte kan användas för att validera JSON. Parsern för Kwalify följer inte specifikationen för YAML fullt ut [25].

type: //rec required:

from: //str to :

type : //arr length: { min: 1 }

contents: { type: //str } subj: //str

body: //str optional:

user: /example.com/account

Figur 16. Exempel på Rx-schema i YAML-format.

JSON Schema liknar Kwalify, anpassat för Javascript med lite tillägg [26].

{"description":"A person", "type":"object",

"properties":

{"name": {"type":"string"}, "age" : {"type":"integer", "maximum":125}}

}

Figur 17. Exempel på JSON Schema

Ingen av de här formaten har nått samma mognadsgrad som Kwalify. Inget tyder heller på just Kwalify skulle vara det vinnande formatet. Alla format inklusive Kwalify är fortfarande förslag från enskilda utvecklare. Det här visar också att utvecklare inte är nöjda med Kwalify, formatet har liten spridning eller att bristerna är så pass stora att de hellre tar fram ett nytt format. Än så länge är de här olika formaten, inklusive Kwalify, argument i en pågående process för ett eventuellt framtida schema- format för YAML och JSON.

2.5 Andra implementationer av YAML för CLI

Det finns många försök till implementationer av YAML för CLI. De här projekten använder sig inte av schema-format, till skillnad från det här arbetet.

Yaml Library for .NET är den mest mogna av implementationerna. Det enda fungerande projektet. Ett arbete av två studenter. Många bra idéer och välstrukturerat.

Utvecklingen har stannat av [27]. Projektstart: 2006-08-31.

Yamldotnet är ett projekt som inte existerade när det här arbetet startade. Mycket utvecklat under kort tid [28]. En portning av Libyaml [29]. Projektstart: 2008-07-29.

Nyaml. Inte fortsatt projekt. Programmet gick inte köra [30]. Projektstart: 2007-12-10.

(15)

Yaml4net. Projektplats finns, men innehåller ingen kod eller programvara [31].

Projektstart: 2005-02-14.

Yaml for .NET and Powershell. Projektplats finns, men innehåller varken kod eller programvara [32].

Yaml.NET är ett inte fortsatt projekt som startade efter påtryckningar på ett forum [33], med många önskemål om att en implementation av YAML behövs på .NET.

Innehåller kvalitetskod, dock inte färdigutvecklat [34].

(16)

3 Krav

Då Nkwalify är ett bibliotek för att konvertera mellan ett typsystem och två textsfilformat, används specifikationerna för typsystemet och textfilsformaten som krav för biblioteket. Typsystemet CTS (Common Type System) är en del av specifikationen för CLI (Common Language Infrastructrure). Standarden ECMA-335 specifierar CLI inklusive CTS [14]. För att att undvika användningen av ännu en förkortning, används CLI även i betydelsen CTS. Boken Common Language Infrastructure Annotated Standard [20] har används för att förstå CLI och dess typsystem.

För YAML används specifikationsdokumentet YAML 1.1 [11]. För Kwalify används dess handledning [17]. Exemplen i specifikationer och handledningar ska kunna köras. Enhetstester görs för att verifiera att kraven uppfylls.

Målet är att så många datatyper som möjligt ska kunna konverteras och återskapas.

3.1 YAML

Laddningen översätter nyckeltabeller, listor och enkla värden i YAML till den omfattande samling av datatyper i .NET. Dumpningen översätter alla datatyper med data till YAML utan att förlora strukturinformation, så att det går att återskapa strukturerna. Krav för implementation av YAML:

Implementation av YAML 1.1 i CLI.

Portning av dumpningsrutinerna i referensimplementationen Pyyaml [36].

Se till att exemplen i specifikationen för YAML fungerar.

3.2 Kwalify

Portning av Kwalify 0.7.1 till i CLI.

Se till exemplen i guiden för Kwalify fungerar.

Egna regler ska kunna definieras och valideras.

3.3 Ladda och dumpa klasser och objekt

Klasser som uppfyller POCO-reglerna ska kunna dumpas till Kwalify-filer

Objekt som uppfyller POCO-reglerna ska kunna dumpas till Yaml-filer och laddas som instanser av definioner i Kwalify-filer.

3.4 Nhibernate

Möjlighet att dumpa och ladda Nhibernate-objekt.

(17)

4 Konstruktion

Nkwalify består av två flöden: Ett laddningsflöde från textformat till CLI-objekt och ett dumpningsflöde från objekt och klasser till textformat.

Figur 18. Nkwalify med flödena Dump och Load.

4.1 Loader – Laddning

Laddningsflödet deserialiserar ett objekt.

Parser - Skapar Yaml-representation ur textfil.

Validator - Validerar Yaml-representationen.

Constructor - skapar CLI-objekt ur Yaml-representationen. Indata för Constructor är ett Yaml-representation med data (objektet) och ett Kwalify- schema som en Yaml-representation med information om klassen.

4.2 Dumper - Dumpning Dumpningsflödet serialiserar ett objekt.

Representer - Skapar Yaml-noder ur klasser och objekt

Serializer - Skapar en textpresentation av Yaml-noder YAML-

representation Hash, List,

Scalar

Representer Serializer

Constructor Parser

Load Dump

.NET objekt textfil i

YAML-format

(18)

5 Implementering

Nkwalify skrevs till största del i Boo på utvecklingsplattformen Sharpdevelop.

Arbetet började med portning av Kwalify från Ruby. Därefter portades delar Pyyaml från Python. Slutligen gjordes ändringar för att anpassa Nkwalify till CLI.

5.1 Verktyg

Som programmeringsspråk valdes Boo för att:

1. Det är intressant och lärorikt att prova något annat språk än C# och jämföra språken.

2. Förmodat kortare utvecklingstid jämfört med C# eftersom Boo kräver mindre skrivande för att uttrycka samma sak.

3. Eftersom portning skulle ske från Python och Ruby underlättas översättningen jämfört med C#.

4. Inbyggd stöd för Boo i Sharpdevelop och Monodevelop, vilket utesluter andra alternativspråk.

Som utvecklingsplattform valdes Sharpdevelop på Windows och Monodevelop på Linux.

Källkoden lagrades först på egen Subversion-server. Efter en månads programmerande lades projektet med källkod på sourceforge (Se http://sourceforge.net/projects/nkwalify/) och utvecklingen fortsatte därifrån, med dagliga in- och utcheckningar.

Reflector ger information om innehållet i PE-filer (exe-filer och dll-filer). Det vill säga man kan grafiskt se den kompilerade klasstrukturen i och även titta på koden i olika programspråk [35].

Jetbrains dottrace är ett profileringsverkyg som ger en grafisk representation av vilka metoder som är mest minnes- eller processorkrävande [36].

Subversion (SVN) är en versionshanterare [37]. På arbetsplatsen används Microsofts versionshanterare Sourcesafe [38]

Sharpdevelop är ett utvecklingsplattform liknande Visual Studio, men med inbyggd stöd för Boo [39].

Monodevelop är ett utvecklingsplattform för Mono på Linux [40]. Tyvärr följer en äldre version av Boo med installationen. Det var frustrerande att arbeta med Monodevelop, så utvecklingen fortsatte enbart på Sharpdevelop. Tanken var från början att använda Sharpdevelop på arbetsplatsen och Monodevelop på fritiden. Om tid och intresse finns bör byggfiler göras även för Mono-plattformen på Linux.

(19)

5.2 Implementering

Scannern implementerades med inspiration från Ruby:s StringScanner [44], och då Kwalify inte har rutiner för dumpning implementerades en sådan rutin med inspiration av referensimplementationen Pyyaml[29]. Validator och Parser började som direkta portningar av Kwalify, men har efter tester och experiment, gjorts om.

Klassen Yaml är det allmänna gränssnittet utåt. Enligt specifikationen för YAML skall en YAML-implementation innehålla en Dump- och en Load-metod.

Metoden Dump anropar först Representer som skapar en YAML-representation av objektet eller klassen som matas in, resultatet matas in i Serializer som returnerar en textrepresentation av YAML-representationen.

Metoden Load med ett argument används för att skapa Yaml-representationer.

Det vill säga antingen en skalär (IConvertible), en hashtabell (HashTable) eller en lista (ArrayList). Här sker ingen validering.

Metoden Load med två argument används när en textpresentation skall bli ett objekt. Första argumentet är textpresentationen, det vill säga YAML-filen, och det andra argumentet är klassen som ska instansieras. YAML-filen parsas till en YAML- representation och klassen representeras till YAML-representation. Därefter sker validering där den representerade klassen fungerar som schema

Textpresentationen matas in i Parser som returnerar en YAML-representation av den. Klassen matas in i Representer som gör YAML-presentation av klassen. Båda matas sedan in i Constructor som skapar en instans av klassen med det data som angavs ursprungligen som textpresentation. Texten som matades in blir en instans av klassen T. Ett objekt av typ T.

class Yaml:

[property(Errors)]

_errors = Logger.Instance

static def Dump(obj as object):

return Serializer().Serialize(Representer().Represent(obj))

static def Load(str as string):

return Parser().Parse(str)

static def Load(str as string, T as System.Type):

return Constructor().Construct(

Representer().Represent(T), Parser().Parse(str))

Figur 19. Klassen Yaml i Nkwalify.

Validering sker i klassen Constructor. Validering kan också användas utanför Constructor, då ett dokument ska kontrolleras mot en definierad schema.

Se bilaga 2 för fullständigt klassträd av Nkwalify.

(20)

6 Test

Enhetstester utfördes under utvecklingen och prestandatester utfördes i slutet av utvecklingen. Jämförande prestandatester mot Xmlserializer utfördes för att få en uppfattning om hur Nkwalify presterar mot en referensimplementation för serialisering på CLI.

6.1 Enhetstester

Enhetstester utvecklades och kördes med jämna mellanrum under framtagningen av programvaran. Enhetstestesterna visade sig vara till stor nytta, då många fel upptäcktes tidigt vid körningarna. Enhetstesterna består av laddning och dumpning av kraven specificerade under kapitlet Krav, samt undersökning av specialfall.

6.2 Jämförande körningar med Parser, Serializer, Representer och Constructor

En klass Y som innehåller en lista av heltal, en lista av listtyp, ett heltal, en teckensträng, ett booliskt värde, en hashtabell, en referens en annan klass X som har referenser till klasserna Y, X, Z och slutligen tomma klassen Z. Klasserna innehåller både direkta cirkulära referenser och flera nivåers cirkulära referenser.

| DUMP | LOAD Loopar| Represent Serialize | Parse Construct 1000 | 63 31 | 469 516 2000 | 109 31 | 781 938 3000 | 156 63 | 1156 1422 4000 | 219 78 | 1531 1953 5000 | 266 109 | 1938 2391 6000 | 328 109 | 2313 2875 7000 | 406 141 | 2703 3359 8000 | 469 156 | 3078 3844 9000 | 500 172 | 3500 4406 10000 | 531 203 | 3859 4875

Figur 20. Tiden i millisekunder för de olika processtegen.

Profileraren visar att 8 av 10 mest processorkrävande rutinerna har att göra med parsningen: Match, IsMatch, ContainsKey, get_Item, Substring står högst upp på listan. De ingår alla i parsningens reguljära uttryck och sökning i hashtabellen som innehåller de reguljära uttrycken. Ett arbete med prestandajusteringar påbörjades.

Först provades att kompilera alla uttryck i förväg. Det krävde lång starttid och mycket minne. Förkompileringen är onödig då alla uttrycken kanske inte används.

Genom att fylla en global hashtabell med uttryck när de används första gången, blev starttiden kortare och onödig kompilering undveks. Vid matchningen söks hashtabellen efter uttryck istället för att skapa en ny. Om uttrycket inte finns - skapas det.

Men även efter justeringarna är matchningen med reguljära uttryck den mest processorkrävande rutinen. 26% av processortiden går åt att matcha uttryck, 5 % går

(21)

att undersöka om uttrycket finns i tabellen och 5% går att hämta uttrycket. Resterande tid går åt till upp till hundra andra rutiner.

6.3 Dumpa vektorer

Belastningstesterna visar hur snabbt stora mängder data kan bearbetas och om det finns någon övre gräns. I figur 21 redovisas dumpning av stora vektorer. Kolumnen längst till vänster visar antal element i vektorn som matas in. Kolumnen längst till höger visar filstorleken i bytes i den utmatade filen.

| size (unicode characters) / time (ms) items | represe | serial | total | bytes 00 100 000 | 011 615 | 09 956 | 05 361 | 002 177 780 00 200 000 | 073 244 | 11 268 | 09 766 | 004 577 780 00 400 000 | 075 022 | 11 542 | 10 003 | 009 377 780 00 800 000 | 067 477 | 10 844 | 09 343 | 018 977 780 01 600 000 | 050 404 | 12 354 | 09 922 | 039 377 780 03 200 000 | 049 832 | 11 887 | 09 597 | 080 977 780 06 400 000 | 044 149 | 12 275 | 09 605 | 164 177 780

Figur 21. Dumpning av vektorer mätt i antal tecken per millisekund.

Eftersom dumpningshastigheten håller sig runt 19 kB per millisekund oberoende av antalet element, har dumpningen en komplexitet på O(n). Den växer linjärt.

6.4 Jämförande prestandatester med Xmlserializer

Xmlserializer är fem gånger snabbare vid dumpning och laddning. Xmlserializer är förmodligen så optimal en parser för XML kan bli. Nkwalify är däremot långtifrån optimal. Parsern i Nkwalify är inte en äkta parser, utan den använder sig av reguljära uttryck. Boken Compilers - Principles, Techniques and Tools [42] användes för att undersöka hur en parser skulle implementeras. Tyvärr räckte inte tiden till att implementera en sådan.

| XML | YAML

N | tid (ms) N/ms | tid (ms) N/ms 1000 | 375,00 2,67 | 984,38 1,02 2000 | 406,25 4,92 | 1625,00 1,23 3000 | 781,25 3,84 | 2093,75 1,43 4000 | 843,75 4,74 | 3171,88 1,26 5000 | 1015,63 4,92 | 4046,88 1,24 6000 | 1390,63 4,31 | 4640,63 1,29 7000 | 1625,00 4,31 | 5421,88 1,29 8000 | 1875,00 4,27 | 5890,63 1,36 9000 | 2109,38 4,27 | 6531,25 1,38 10000 | 1968,75 5,08 | 8000,00 1,25

Figur 22. Jämförande dumpning och laddning av N antal objekt.

Utan validering sker dumpning och laddning betydligt snabbare. I genomsnitt processas då ca 1,74 objekt per millisekund, jämfört med ca 1,13 objekt per millisekund med validering.

Användningen av boxing och casting leder till prestandaförluster. Objekten är inte definierade datatyper, ytan är allmänna objekt som sedan konverteras till rätt

(22)

datatyp. Egendefinierade trädstrukturer skulle förmodligen göra både dumpning och laddning ännu snabbare.

Dumpningen utför Nkwalify betydligt snabbare än XMLSerializer. Där är förhållandet tvärtom. Varför det är så stor skillnad har inte utretts pga tiden inte räckte till.

| XML | YAML N | tid (ms) N/ms | tid (ms) N/ms 1000 | 250,00 4,00 | 31,25 32,00 2000 | 140,63 14,22 | 46,88 42,67 3000 | 218,75 13,71 | 78,13 38,40 4000 | 281,25 14,22 | 93,75 42,67 5000 | 359,38 13,91 | 125,00 40,00 6000 | 453,13 13,24 | 140,63 42,67 7000 | 484,38 14,45 | 171,88 40,73 8000 | 562,50 14,22 | 218,75 36,57 9000 | 656,25 13,71 | 218,75 41,14 AVG | 378,47 12,86 | 125,00 39,65

Figur 23. Jämförande dumpning av N antal objekt.

6.5 Utökning av valideraren med egna regler

En klass ExtendedValidator utökar klassen Validator. Den nya klassen innehåller nya regler. Därefter matas två filer till denna utökade validator för att validera den ena (answers) mot den andra med de utökade reglerna (answers_schema). Figur 24 visar ExtendedValidator med test.

class ExtendedValidator(Nkwalify.Validator):

def constructor(obj as object):

super(obj)

def ValidateHook(val as object, rule as Rule, path as List,

errors as ArrayList):

if rule.Name:

if rule.Name == 'Answer':

h as Hash = val

if h['answer'] == 'bad':

reason = h['reason']

if not reason:

errors.Add(

Nkwalify.Errors.ValidationError('No reason') )

...

[Fact]

def ValidatorHookTest():

answers_schema = """

type: map mapping:

"answers":

type: seq sequence:

- type: map name: Answer

(23)

mapping:

"name": { type: str, required: yes } "answer": { type: str, required: yes, enum: [good, not bad, bad] } "reason": { type: str }

"""

answers = """

answers:

- name: Foo answer: good

reason: I like this style.

- name: Bar answer: not bad - name: Baz answer: bad

reason: I don't like this style.

"""

v = ExtendedValidator(

Parser().Parse(

IO.StringReader(answers_schema) )

)

es = v.Validate(Parser().Parse(IO.StringReader(answers))) for e in es:

print e

assert es.Count == 0

Figur 24. Test för utökning av valideraren.

6.6 Dumpa produktmodeller

Dumpning av Nhibernate-klasser är ett av kraven för Nkwalify. Här testas dumpning av Nhibernate-klassen Produktmodell. Eftersom Produktmodeller innehåller attribut som inte ska dumpas, krävdes en välbehövlig ändring av Representer-klassen. Vid dumpning kan man nu ange en lista med klass-attribut som inte ska tas med.

Ytterligare tester gjorde för de andra klasserna i systeminställningar. Dumpningen genomfördes utan problem.

def PMTest():

hiddenfields = {

'FeatureClassNameLong': null, 'Id': null,

'Status': null }

for pm as ProduktModell in

TopoKlienten.Logic.ProduktModell.GetAll(NHibernateTopo.NHSession):

print Nkwalify.Serializer().Serialize(

Nkwalify.Representer(hiddenfields).Represent(pm) )

Figur 25. Dumpning av Nhibernate-klassen Produktmodell.

(24)

7 Diskussion

Formatet Kwalify visade sig inte vara tillräckligt för representera alla förekommande datatyper i CLI. Det leder till att Nkwalify inte kan användas för alla datatyper.

7.1 Formatet Kwalify

Kwalify är ingen formell standard, utan ett förslag från en enskild utvecklare.

Inklusive Nkwalify finns idag fyra implementationer av Kwalify. Det behövs en standard eller konsensus kring ett schema för YAML och JSON när antalet implementationer växer. Förslagsvis en standard med inspiration från JSON Schema, Rx, Kwalify, Doctrine och YAML Tags. Framförallt är det önskvärt med bättre och flexiblare stöd för olika datatyper samt att formatet ger möjlighet att specificera datatyper mer detaljerat.

En hashtabell som inte har bestämda nyckelnamn, men däremot har bestämda typer på nyckeln, kan inte specificeras i Kwalify.

Valideraren godkänner inte attributlösa klasser.

Brister i hur datatyper specificeras. I grunden räcker det med hashtabell, lista och skalära värden. Men det är svårt att definiera begränsningar. T ex vektorer har begränsningar i hur långa de kan vara. Hur representerar man köer och stackar?

Allmänt dåligt stöd för olika datatyper. Det går inte beskriva vissa mer komplicerade strukturer, t ex parametriserade datatyper.

7.2 Problem med implementationen Nkwalify De brister som Kwalify har ärvs också av Nkwalify.

Laddningen stödjer inte parametriserade datatyper i parametriserade datatyper.

Enbart en nivå stöds. Dvs Generic.List<string> stöds men inte Generic.List<Generic.List<string>>.

Laddningen stödjer inte Vektorer som innehåller vektorer, listor eller hashtabeller.

Datatyperna Queue och Stack stöds inte. Det är omöjligt att särskilja datatyperna från vanliga listor i Kwalify.

Default-värden för hashtabeller stöds inte, då sådant finns inte i CLI.

Yaml:s Enum-datatyp stöds inte.

Det går inte inte ladda egendefinierade parametriserade datatyper.

En lista som bara innehåller en lista som i sin tur bara innehåller en lista som i sin tur innehåller något annat ger fel resultat vid parsningen. Detta för att undvika StackOverflowException vid listor som refererar till sig själv.

Constructorn ser inte skillnad mellan djupt länkade listor och listor som refererar till sig själv och skapar därmed en referens, vilket är fel. Någon lösning på detta problem har inte hittats.

Klassen Representer stödjer inte cirkulära referenser i listor.

(25)

7.3 Önskemål för implementationen Nkwalify

Under utvecklingen växte listan med önskemål för framtida förbättringar av Nkwalify.

Ta med information om paketet (assembly) som en klass tillhör, dvs namn, version, kultur och eventuell global identitet. Funktionen finns - men har inte aktiverats då det kan leda till problem för andra implementationer av Kwalify.

Det här bör först utredas.

Hitta en lösning på problemet med listor i listor alternativt en annan lösning på problemet med listor som refererar till sig själva

Lista vilka attribut man inte vill ta med genom att ange klassnamn och attributnamn, motsvarande attributet [XmlIgnore] i XMLSerializer.

Begränsa hur långt ner i objektträdet man ska serialisera och hur göra med referenser till objekt som inte serialiseras.

Representera och serialisera på bredden först. Idag sker dumpningsprocessen med djupet först. Genom att dumpa på bredden först gör att referenser kan hanteras smidigare.

Samla hanteringen av typer till en klass per typ. Idag är hanteringen spridd och inbyggd i de olika dumpnings- och laddningsklasserna.

Bygga in möjlighet att kompilera nya klassbibliotek från Kwalify-filer.

Genom att använda klasserna och metoderna i System.Reflection.Emit kan Kwalify-filerna kompileras och sparas som DLL-filer [45].

Stödja strömmande text. Då kan de reguljära uttrycken ersättas. Det ger en implementation mer lik den normativa implementationen och prestandan ökar.

Fördelen är också att hela dokumentet inte först behöver laddas till minnet. I nuläget är matchningen av reguljära uttryck det mest tidskrävande momentet.

Själva matchningen går snabbt, men CLI skapar ett nytt Match-objekt för varje matchning, vilket kräver resurser.

Arbeta mot .NET 2.0 fullt ut. I dagsläget är Nkwalify gjort så att det någorlunda enkelt ska kunna översättas till .NET 1.0. Genom att använda parametriserade datatyper undviks den typkonvertering och den typkontroll som sker idag.

Implementera en datatyp för att traversera noder i en graf. Datatypen har inte implementerats då ingen elegant lösning har hittats. Några försök har gjorts men kasserats, då försöken inte är bättre än att ha ett objekt som konverteras till ett av gränssnitten IList, IDictionary eller IConvertible.

Särskilja på Validator och Parser så att Parser parsar och skapar filinformation under parsningen. Valideraren använder enbart Yaml- datastrukturer för valideringen. Vid fel används filinformation för att få radnummer. Detta underlättar både parsningen och valideringen. Nkwalify blir modulär och snabbare.

XMLSerializer laddar data snabbare än Nkwalify. Dumpning av data går däremot snabbare med Nkwalify. Ett önskemål är givetvis att även laddningen ska ske snabbbare än med XMLSerializer.

(26)

8 Slutsatser

De frågeställningar som ställdes i början av arbetet besvaras här.

8.1 Frågeställningar

Går det att fullständigt beskriva klasser och objekt i enkla textfiler (serialisering) och kunna ladda in dessa igen (deserialisering)?

Så länge klasserna följer POCO-reglerna, går det att automatiskt serialisera och deserialisera objekt. Om de inte följer reglerna, krävs manuell kodning för att översätta mellan objekt och YAML samt klass och Kwalify.

Hur göra med objekt som refererar till sig själva?

YAML löser problemet med cirkulära referenser med ankare och alias. Tyvärr har inte JSON stöd för ankare och alias.

Går det att serialisera alla förekommande datatyper?

Nej, inte i dagsläget. Kwalify kräver bättre stöd för olika egendefinierade datatyper.

Jämfört med XMLSerializer är dock stödet för datatyper bättre.

Går det att serialisera parametriserade typer (Generics)?

Ja, det går. Men implementationen klarar inte i dagsläget parametriserade typer vars parametrar är parametriserade typer.

Vad går inte att serialisera och varför?

Kwalify kan inte skilja på olika typer av samlingar (Collections) som listor som har samma struktur. Exempelvis Boo.Lang.List och System.Collections.ArrayList. Båda är listor av objekt. Det är svårt att representera samlingar som inte har de vanliga sättet att komma åt elementen, som t ex Stack och Queue.

Jämför serialisering mellan YAML och XML. Hur sker serialisering i .NET?

Serialisering sker med Xmlserializer. I grundkonfigurationen stöds få datatyper jämfört med Nkwalify.

Hur utökad man ett schema med ytterligare begränsningar (constraints)?

Inriktningen på arbetet ändrades något mot att ladda och dumpa så många olika former av objekt som möjligt. Valideringsmöjligheterna har undersöks och testats, men redovisas inte.

Kan ytterligare typer av constraints läggas till Kwalify och i så fall, hur?

(27)

Det fungerar genom att utöka klassen Validator och implementera ValidateHook- metoden. Se exempel i avsnitt 6.5.

Det här examensarbetet visar att det går att skapa en allmän dumpnings- och laddningsrutin som klarar av arbetet utan att speciella översättningsrutiner behövs.

Mycket av valideringen kan också ersättas med schema-filer. Då är valideringen samlad i förhoppningsvis mer lättförståeligt och lättillgängligt format. Det här är en liten prototyp som visar en liten del av vad som går att ersätta.

8.2 Förväntat resultat

Ett bibliotek för validering av JSON och YAML i .NET benämnt Nkwalify. Biblioteket görs tillgängligt för allmänheten.

Biblioteket finns upplagt på http://sourceforge.net/projects/nkwalify/. I biblioteket finns även en prototyp till en applikation för att visa och redigera YAML-filer.

Lantmäteriet får ett sammanhållet paket för att validera, importera, redigera och exportera business-klasser, främst produktmodeller inklusive lagerinställningar och värdeförrådskopplingar.

En prototyp gjordes för import och export av olika business-klasser. Den grovhuggna prototypen fungerar, men Nkwalify saknar vissa önskade inställningsmöjligheter, men kräver långt mindre arbete att färdigställa än att göra en handgjord speciallösning. Ett administrationspaket finns sedan tidigare, baserat på serialiseringsformatet SDL.

8.3 Uppfyllande av kraven

Laddning och dumpning av alla enkla datatyper stöds och allmänna klasser och objekt stöds om de uppfyller POCO-reglerna. Listor och Hashtabeller stöds med vissa undantag för listor. Parametriserade datatyper har inte fullt stöd. Ytterligare utveckling krävs. Kwalify och dess validerare är fullständigt implementerade i Nkwalify.

Laddning och dumpning av Nhibernate-klasser stöds, se avsnitt 6.6. Valideraren går att utöka med egna regler, se 6.5

(28)

9 Referenser

[1] YAML is JSON. Redhanded, 2005-04-08

http://redhanded.hobix.com/inspect/yamlIsJson.html

[2] Richardson, C. Cover Story: What Is POJO Programming? JDJ, 2006.

http://java.sys-con.com/node/180374

[3] Object-relational mapping, Wikipedia. http://en.wikipedia.org/wiki/Object- relational_mapping

[4] Serialization, Wikipedia. http://en.wikipedia.org/wiki/Serialization [5] Data Validation, Wikipedia. http://en.wikipedia.org/wiki/Data_validation [6] Reflection (C# Programming Guide). MSDN. http://msdn.microsoft.com/en-

us/library/ms173183(VS.80).aspx

[7] Liberty, J. Programming C#. OReilly, 2001.

[8] Extensible Markup Language (XML). http://www.w3.org/XML/

[9] Document Object Model (Core) Level 1. W3C, 1998.

http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html [10] Introducing JSON. http://json.org/

[11] Ben-Kiki, O., Evans,Y. & Ingerson, B. YAML Ain’t Markup Language (YAML) Version 1.1, 2005. yaml.org/spec/1.1/

[12] Resnick, P. Internet Message Format. RFC 2822, IETF-NWG, 2001.

http://www.ietf.org/rfc/rfc2822.txt

[13] Crockford, D. The application/json Media Type for JavaScript Object Notation (JSON). RFC 4627, IETF-NWG, 2001. http://www.ietf.org/rfc/rfc4627.txt [14] Standard ECMA-262: ECMAScript Language Specification 3rd edition, 1999.

http://www.ecma-international.org/publications/standards/Ecma-262.htm [15] Configuring an App. Google Code, 2008

[http://code.google.com/appengine/docs/configuringanapp.html ]

[16] YAML. Ruby on Rails, 2007. http://wiki.rubyonrails.org/rails/pages/YAML [17] Kuwata, M. Kwalify User's Guide (for Ruby), 2008. http://www.kuwata-lab.com/

kwalify/ruby/users-guide.html

[18] Rezic, S. Pkwalify. http://search.cpan.org/~srezic/Kwalify-1.19/pkwalify [19] Rezic, S. Kwalify. http://cpan.uwinnipeg.ca/htdocs/Kwalify/README.html [20] Miller, J. Common Language Infrastructure Annotated Standard. Addison-

Wesley, 2004.

[21] CLI Languages, Wikipedia. http://en.wikipedia.org/wiki/CLI_Languages [22] Barreto de Oliveira, R. Boo Manifesto. 2005

http://boo.codehaus.org/BooManifesto.pdf

[23] About the Project. Doctrine. http://www.doctrine-project.org/about

(29)

[24] Manual, Schema Files. Doctrine. http://www.doctrine- project.org/documentation/manual/1_0?chapter=schema-files [25] Why Rx? http://rjbs.manxome.org/rx/

[26] JSON Schema Proposal. http://json-schema.org

[27] Yaml Library for .NET. Sourceforge. http://yaml-net-parser.sourceforge.net [28] Yamldotnet. Sourceforge. http://yamldotnet.wiki.sourceforge.net/

[29] Pyyaml. http://pyyaml.org/wiki/PyYAML

[30] Nyaml. Sourceforge. http://sourceforge.net/projects/nyaml [31] Yaml4net. Sourceforge. http://sourceforge.net/projects/yaml4net

[32] Yaml for .NET and Powershell. Codeplex. http://www.codeplex.com/yaml [33] YAML for .NET, Ruby Forum. http://www.ruby-forum.com/topic/141041 [34] Yamldotnet. http://code.google.com/p/yaml-dot-net/

[35] Reflector. http://www.red-gate.com/products/reflector/

[36] Profiler. http://www.jetbrains.com/profiler/

[37] Subversion. http://subversion.tigris.org/

[38] Source Safe. http://msdn.microsoft.com/en-us/vs2005/aa718670.aspx [39] Sharpdevelop. http://www.icsharpcode.net/OpenSource/SD/

[40] Monodevelop. http://monodevelop.com/

[41] SDL. http://www.ikayzo.org/confluence/display/SDL/Home

[42] Aho, A., Lam, M., Sethi, R. & Ullman, J. Compilers - Principles, Techniques &

Tools. Second Edition. Pearson, 2006.

[43] Libyaml. http://pyyaml.org/wiki/LibYAML [44] StringScanner. Ruby-doc.org. http://www.ruby-

doc.org/core/classes/StringScanner.html

[45] Huene, P. Exploring the System.Reflection.Emit Namespace. Devshed, 2007.

http://www.devhood.com/Tutorials/tutorial_details.aspx?tutorial_id=238

Onlinerefererenser aktuella 2008-09-16.

(30)

Bilaga 1: Ordlista

Boo programmeringsspråk

CLI (Common Language Infrastructure) specifikation för Microsofts motsvarighet till Javas virtuella maskin

CLI-objekt objekt som finns i dotnet eller Mono, men inte i t ex Javas virtuella maskin

CLR (Common Language Runtime)

cirkulär refererens objekt som pekar på sig självt

data binding laddning och automatisk instansiering av en klass dataserialiseringsformat serialiseringsformat

deserialisering laddning

DLR (Dynamic Language Runtime) bibliotek för att kunna köra dynamiska språk på CLI

dumpning (... av data) överföring av data från en dators arbetsminne till beständigt lagringsformat eller annan dator

export dumpning

Hibernate ramverk för objekt-relationell mappning i Java IL (Intermediate Language) bytekod för CLI

import laddning

INI-fil (initieringsfil) filformat för inställningsfiler

inställningsfil fil som sparar data mellan programkörningar IronPython implementation av Python på CLI.

IronRuby implementation av Ruby på CLI

JSON (Javascript Object Notation) filformat för serialisering, främst för överföring av data mellan datorer

konfigurationsfil inställningsfil

Kwalify schemaformat för YAML och JSON

laddning (... av data) överföring av data till en dators arbetsminne från beständigt lagringsformat eller annan dator

Mono Novells implementation av CLI på Linux

Nhibernate ramverk för objekt-relationell mappning (ORM) i .NET

ORM, objekt-relationell mappning översättning mellan ett objektorienterat system och en relationsdatabas

parametriserade typer en. Generic types

(31)

POCO, POCO-regler (Plain Old CLI Object) regler för att kunna generalisera och automatisera hanteringen av objekt

Representer klass i Nkwalify för att skapa en Yaml-representation av ett objekt representera använda Representer-klassen i Nkwalify

SDL filformat för serialisering

schema beskriver strukturen i dokument

schema-format regler för att beskriva strukturen i dokument Serializer klass i Nkwalify för dumpning

serialisera använda Representer-klassen i Nkwalify serialisera dumpa

serialisering dumpning

serialiseringsformat filformat för serialisering skalär enkel datatyp som ex heltal, flyttal, tecken valídering kontroll att värden följer definierade regler valideringsformat schema-format

XML filformat

Xmlserializer klass som ingår i .NET, som som serialiserar objekt till XML YAML filformat

Yaml-representation hashtabell, lista eller skalär

References

Related documents

Under rubrik 5.1 diskuteras hur eleverna använder uppgiftsinstruktionerna och källtexterna när de skriver sina egna texter och under rubrik 5.2 diskuteras hur

To implement such a system, three primitive foreign functions are defined to allow queries to JSON streams using the query language AmosQL of Amos II.. The usefulness of the

Samtliga verktyg som genererar grafiska användargränssnitt utifrån JSON Scheman var anpas- sade för hemsidor (HTML, CSS och JavaScript), vilket hindrade verktygen från att

The same results are obtained for the questionnaire measuring psychopathic traits, were intolerant/violent cluster report significantly higher scores than all the

En lösning på problemet angående kritiska JSON-ändringar i webb-API:er skulle kunna vara att utveckla en webbapplikation, ett verktyg, som testar om ett webb-API:s JSON-meddelanden

En lösning på problemet angående kritiska JSON-ändringar i webb-API:er skulle kunna vara att utveckla en webbapplikation, ett verktyg, som testar om ett webb-API:s JSON-meddelanden

Subject D, for example, spends most of the time (54%) reading with both index fingers in parallel, 24% reading with the left index finger only, and 11% with the right

För att kunna göra mätningar på prestanda, men även bedöma användarvänligheten av de två biblioteken Jansson och YAJL så har jag utvecklat ett testprogram.. Testprogrammet