Kochen mit Patrick

Text
Read preview
Mark as finished
How to read the book after purchase
Kochen mit Patrick
Font:Smaller АаLarger Aa

Inhaltsverzeichnis

Vorwort

Das Borne Sequel

Die Bourne-Übertragung

Immer noch ein seltsames Paar

Eigene Weltanschauung

MS gegen den Test der Welt

LINQe Alternative?

Linqer Populismus?

Freude am Suchen

Wider das Fluchen beim Suchen

Imprint

Vorwort

Programmieren ist wie kochen: Nimm die richtigen, guten Zutaten, bereite alles laut Rezept zu, dann wird zum Schluss etwas Leckeres herauskommen. Für ein Standardessen mag das so stimmen. Doch Spitzenköche und -entwickler bieten weit mehr. Sie experimentieren, probieren aus und kommen auf diese Weise zu noch geschmackvolleren, besseren und funktionaleren Ergebnissen.

Patrick A. Lorenz verbindet Kochen und Programmieren in einer Person. Während er beruflich mit seiner Firma PGK Software & Communication Kunden bei der Verwendung neuer Microsoft-Technologien und der Umsetzung von IT-Lösungen hilft, frönt er in der Freizeit gerne der guten und gesunden Küche. In beiden Bereichen probiert er aus und findet dadurch ganz neue Kreationen.

In der dotnetpro hat Patrick seit 2006 eine feste Kolumne. "Kochen mit Patrick" heißt sie. Darin schreibt er über Technologien, die sein Unternehmen in der Praxis einsetzt oder die es ihm persönlich angetan haben. Getestet und für gut befunden hat er aber auch die Kochrezepte, die in den Kolumnen enthalten sind.

Freuen Sie sich also in diesem devbook über viel Technologie, gewürzt mit einer großen Portion Faszination und tollen Kochrezepten, die das Wasser im Mund zusammenfließen lassen.

Sie erreichen Patrick unter lorenz@pgk.de, www.pgk.de sowie der Facebook-Seite zur Kolumne http://fb.com/Kochen.mit.Patrick.

Kochen mit Patrick: JSON und .NET
Das Borne Sequel


AUTOR

Patrick A. Lorenz ist Geschäftsführer der PGK GmbH, eines auf .NET spezialisierten Technologiedienstleisters, der das .NET-basierte CMS QualiSite anbietet. Daneben ist er als Autor und Coach tätig. In seiner Freizeit ist Patrick Hobbykoch. Sie erreichen ihn unter www.pgk.de, lorenz@pgk.de und www.facebook.com/Kochen.mit.Patrick.

Im vorangegangenen Heft habe ich an dieser Stelle über JSON, die JavaScript Object Notation, berichtet. Es ging um die Grundlagen, den Aufbau von JSON, die Unterschiede zu XML und die Anwendung in der Praxis. Als Fazit ließ sich unter anderem festhalten, dass JSON in klassischen Web-Szenarien XML längst abgelöst hat. Feststellen ließ sich aber auch, dass der Einsatz nicht aufs Web begrenzt ist. Zudem kann nicht nur JavaScript mit JSON umgehen. Eher am Rande habe ich die implizite Serialisierung durch das ASP.NET Web API demonstriert. Microsoft setzt hier auf die verbreitete Open-Source-Bibliothek JSON.NET. Nach dem positiven Feedback möchte ich in diesem Monat mit Ihnen einen zweiten Blick auf diese und andere Komponenten werfen.

Meet JSON.NET

Die Aufgaben von JSON.NET [1] sind einfach umrissen, denn es sind nur zwei an der Zahl:

 die Serialisierung von .NET-Daten in JSON-Strukturen und

 das Deserialisieren in umgekehrter Richtung.

Diese Möglichkeiten gibt es in der .NET Framework Class Library zwar von Haus aus schon, doch JSON.NET will es schneller, komfortabler, flexibler oder schlicht gesagt besser machen.

JSON.NET kann ab .NET Version 2.0 genutzt werden, steht für Windows Phone und Windows 8 zur Verfügung und lässt sich über Mono auch auf anderen Plattformen einsetzen, etwa auf mobilen iOS- oder Android-Geräten. In Visual Studio führt der schnellste Weg zu JSON.NET über NuGet. Mit der folgenden Zeile in der Package Manager Konsole wird die Bibliothek heruntergeladen und in Ihr Projekt eingebunden:

PM> Install-Package Newtonsoft.Json

Anschließend können Sie einfache .NET-Datenstrukturen mit nur einem Aufruf in JSON umwandeln:

var person = new Person {

ID = 1,

FirstName = "Theodor",

LastName = "Heuss"

};

var json = JsonConvert.SerializeObject(person);

Debug.WriteLine(json);

Das Ergebnis sieht so aus:

>{"ID":1,"FirstName":"Theodor","LastName":"Heuss"}

Für bessere Lesbarkeit unterstützt JSON.NET auch eine formatierte Serialisierung, die die Objekthierarchie mittels Einrückung sichtbar macht:

var json = JsonConvert.SerializeObject( person, Formatting.Indented);

Leserlich formatiert zeigt sich die Datenstruktur dann wie folgt:

{

"ID": 1,

"FirstName": "Theodor",

"LastName": "Heuss"

}

Umgekehrt geht es auch: JSON.NET kann aus einer JSON-Zeichenkette ein .NET-Objekt deserialisieren:

var deserializedPerson = JsonConvert.DeserializeObject<Person>(json);

Steht eine passende Klasse nicht zur Verfügung, kann diese als dynamischer Typ als eine Art Prototyp übergeben werden. Das sieht dann so aus:

var deserializedAnonymousType = JsonConvert.DeserializeAnonymousType( json, new {

FirstName = string.Empty,

LastName = string.Empty

});

Debug.WriteLine( deserializedAnonymousType.LastName);

Offiziell unterstützt JSON.NET darüber hinaus dynamische Objekte. In Verbindung mit dem Schlüsselwort kann ohne explizite Übergabe eines Datentyps typisiert auf Eigenschaften zugegriffen werden:

dynamic deserializedDynamicType = JsonConvert.DeserializeObject<dynamic>(

json);

Debug.WriteLine( deserializedDynamicType.LastName);

Wenngleich formal unterstützt, funktioniert dies leider nicht, sondern wird mit einem Laufzeitfehler quittiert. Zumindest bei mir. Ich habe mich in der Vergangenheit schon einmal mehrere Stunden mit diesem Problem gequält; damals wie heute völlig erfolglos. Vielleicht haben Sie mehr Glück?

JSON.NET für die schwierigen Fälle

JSON.NET ist nicht auf einfache Strukturen begrenzt. Es lassen sich Arrays, Dictionaries und komplexe Objektbäume damit umwandeln. Im folgenden Beispiel werden drei Klassen in Collections ineinander verschachtelt. Abgebildet wird ein einfaches Artikelarchiv aus Ausgaben mit Artikeln und Autoren:

var issues = new List<Issue> {

new Issue {

Title = "dotnetpro",

Year = 2013,

Number = 12,

PublicationDate = new DateTime(2013, 11, 21),

Articles = new List<Article> {

new Article {

Title = "Kochen mit Patrick",

PageNumber = 123,

Authors = new List<Author> {

new Author {

FirstName = "Patrick A.",

LastName = "Lorenz"

}

}

}

}

}

};

Mit den weiter oben gezeigten Aufrufen produziert JSON.NET aus der Struktur ein ansehnliches Stück JSON:

[{

"Title": "dotnetpro",

"Year": 2013,

"Number": 12,

"PublicationDate": "2013-11-21T00:00:00",

"Articles": [

{

"Title": "Kochen mit Patrick",

"PageNumber": 123,

"Authors": [

{

"FirstName": "Patrick A.",

"LastName": "Lorenz"

}

]

}

]

}]

Offiziell unterstützt JSON keine Datumswerte. Hier spielt JSON.NET seine Stärken aus: Die Bibliothek bietet eine ausgesprochen umfangreiche Unterstützung von JSON mit sehr vielen Details und Spezialfällen. Datumswerte in verschiedenen gängigen Interpretationen gehören da schon zu den Basics.

JSON versus XML

Obwohl oder gerade weil man JSON und XML in manchen Anwendungsbereichen als Konkurrenten betrachten darf, bietet JSON.NET eine XML-Unterstützung. Diese erlaubt mit gewissen Einschränkungen die Konvertierung von JSON nach XML:

var issueJson =

JsonConvert.SerializeObject(

issues[0]);

 

var xml =

JsonConvert.DeserializeXmlNode(

issueJson, "issue");

Debug.WriteLine(xml.OuterXml);

Die Zeilen basieren auf dem vorherigen Beispiel und produzieren das folgende XML:

<issue>

<Title>dotnetpro</Title>

<Year>2013</Year>

<Number>12</Number>

<PublicationDate>2013-11-21T00:00:00 </PublicationDate>

<Articles>

<Title>Kochen mit Patrick</Title>

<PageNumber>123</PageNumber>

<Authors>

<FirstName>Patrick A.</FirstName>

<LastName>Lorenz</LastName>

</Authors>

</Articles>

</issue>

Der Prozess lässt sich auch umkehren, allerdings mit Reibungsverlusten.

Im konkreten Beispiel geht die Abbildung der Unterstrukturen als Array verloren, im Vergleich zum JSON weiter oben fehlen die eckigen Klammern. Folglich lässt sich das rückermittelte JSON nicht mehr mit in das Ursprungsobjekt deserialisieren.

{ "Title": "dotnetpro",

"Year": "2013",

"Number“: "12",

"PublicationDate": "2013-11-21T00:00:0",

"Articles": {

"Title": "Kochen mit Patrick",

"PageNumber": "123",

"Authors": {

"FirstName": "Patrick A.",

"LastName": "Lorenz"

}

}

}

Für Faule wie mich: Code-Generierung

Zwar erlauben Bibliotheken wie JSON.NET den unstrukturierten Zugriff auf JSON-Daten mittels Dictionaries, wirklich interessant werden sie aber erst in Verbindung mit typisierten Klassen, die sich per Knopfdruck befüllen lassen. Wer mit einer externen Schnittstelle arbeitet, wird die dazu notwendigen Datenstrukturen in der Regel nicht vorliegen haben. Hier hilft der JSON C# Class Generator [2].

Das in Abbildung 1 gezeigte Programm besteht aus einem großen Eingabefeld und diversen Einstellungsmöglichkeiten. In das Feld wird ein möglichst aussagekräftiges Beispiel der zu verarbeitenden JSON-Struktur kopiert. Mit den Optionen lässt sich festlegen, ob die erzeugten Klassen Felder oder Eigenschaften verwenden sollen, welche Sichtbarkeit sie haben sollen, in welchem Namespace sie abgelegt werden und so weiter.


[Abb. 1] Der JSON C# Class Generator erzeugt aus einem JSON-Beispiel

eine passende Klassenstruktur.

Per Klick erzeugt das Programm eine passende Klassenstruktur entweder in C# oder Visual Basic. Die erkennbaren -Attribute gehören zu JSON.NET, das vom Programm explizit unterstützt wird. Sie dienen dem Mapping zwischen der JSON-Struktur und den Eigenschaften der Klasse. Im vorliegenden Fall ist das unnötig, lässt sich jedoch leider nicht abschalten.

namespace JSON.NET3 {

...

public class Issue {

[JsonProperty("Title")]

public string Title { get; set; }

[JsonProperty("Year")]

public int Year { get; set; }

[JsonProperty("Number")]

public int Number { get; set; }

[JsonProperty("PublicationDate")]

public string PublicationDate { get; set; }

[JsonProperty("Articles")]

public Article[] Articles { get; set; }

}

}

Als dritte Sprache neben C# und Visual Basic wird von JSON.NET übrigens TypeScript unterstützt:

module JSON.NET3 {

export interface Author {

FirstName: string;

LastName: string;

}

export interface Article {

Title: string;

PageNumber: number;

Authors: Author[];

}

export interface Issue {

Title: string;

Year: number;

Number: number;

PublicationDate: string;

Articles: Article[];

}

}

Als TypeScript-Fan finde ich das besonders spannend. Interessant ist das vor allem, um clientseitig aus TypeScript/ JavaScript typisiert auf ein externes API zugreifen zu können, im Zweifelsfall auch ganz ohne .NET. Für die kleine C#-Klasse zwischendurch gibt es unter [3] mit json2csharp eine Online-Version des Konverters (Abbildung 2).


[Abb. 2] C#-Datenstrukturen auf Knopfdruck.

Was JSON.NET nicht kann

In der Mehrzahl der Fälle liegen JSON-Strukturen nicht einfach so herum und warten darauf, deserialisiert zu werden. Meist wird JSON per HTTP mit REST-basierten Web-Diensten ausgetauscht – in beide Richtungen, versteht sich. JSON.NET konzentriert sich voll auf die Serialisierung und Deserialisierung. Der Datenaustausch gehört dagegen nicht zum Funktionsumfang. Der native Weg in .NET, Daten per HTTP abzufragen, führt über die -Klasse.

Das nachfolgende Beispiel zapft das Google Geocoding API [4] an und führt mit diesem eine Geo-Codierung für die recht unscharfe Adresse aus. Die Parametrisierung erfolgt über den Query-String. Der Web-Dienst liefert eine JSON-Struktur zurück, die mittels der gezeigten Funktionen von JSON.NET in ein zunächst untypisiertes Objekt deserialisiert werden kann.

using (var client = new WebClient()) {

client.Encoding = System.Text.Encoding.UTF8;

const string url = "http://maps.googleapis.com/maps/api/ geocode/json? address=Freiburg&sensor=false";

var jsonStr = client.DownloadString(url);

var result =

JsonConvert.DeserializeObject( jsonStr);

Debug.WriteLine(result);

}

Zwar funktioniert dieser Ansatz, als sonderlich komfortabel muss man ihn aber nicht bezeichnen. Alternativ gibt es diverse Bibliotheken und Erweiterungen, die auf JSON.NET aufbauen und dessen Funktionsumfang um eine HTTP-Kommunikationsschicht ergänzen. RestSharp [5] ist eine davon – oder vielmehr war es. Die Bibliothek kapselt den Zugriff auf REST-basierte Web-Dienste und erlaubt dem .NET-Entwickler deren komfortable Bedienung. Als Datenformate werden XML und JSON unterstützt.

Die Einbindung in Ihr Projekt erfolgt wie gewohnt per NuGet:

PM> Install-Package RestSharp

Die Bibliothek konzentriert sich auf drei Strukturen. konfiguriert einen Endpunkt. Mit werden einzelne Abfragen zusammengestellt. Deren Ergebnis wird als zurückgeliefert.

Die folgenden Zeilen führen die identische Abfrage mit dem Google Geocoding API durch:

var client = new RestClient {

BaseUrl = "http://maps.googleapis.com"

};

var request = new RestRequest( "maps/api/geocode/json");

request.AddParameter( "address", "Freiburg");

request.AddParameter( "sensor", "false");

var result = client.Execute(request);

Debug.WriteLine(result.Content);

Im Beispiel ist sehr schön zu erkennen, wie sauber sich Abfragen mit RestSharp strukturieren und mittels Parametern qualifizieren lassen.

Die JSON-Rückmeldung des Web-Dienstes wird von als Zeichenkette geliefert und testweise im Output-Fenster ausgegeben.

Freiburg wird natürlich gefunden und Google spendiert unter anderem passende Geo-Koordinaten:

...

"formatted_address" : "Freiburg, Germany",

"geometry" : {

"location" : {

"lat" : 47.9990077,

"lng" : 7.842104299999999

},

...

Statt als String kann das Ergebnis ähnlich wie bei JSON.NET in eine .NET-Klassenstruktur deserialisiert werden:

...

var result = client.Execute<GeoResult>(request);

foreach (var geoResult in result.Data.results) {

Debug.WriteLine( geoResult.formattedAddress);

Debug.WriteLine("Lat: {0}, Lng: {1}", geoResult.geometry.location.lat,

geoResult.geometry.location.lng

);

}

Die notwendige Klassenstruktur habe ich im Vorfeld manuell angelegt. Sie muss recht engen Vorgaben genügen, ansonsten scheitert die Deserialisierung und die Komponente liefert schlicht .

Früher hat an dieser Stelle JSON.NET intern seinen Dienst verrichtet. Dies hat der RestSharp-Entwickler in den jüngsten Versionen jedoch zugunsten einer Eigenentwicklung aufgegeben. Wer lieber mit JSON.NET arbeitet, kann dessen Unterstützung mit wenigen Zeilen integrieren. Dazu bedarf es eines eigenen Deserialisierers als Brücke zwischen RestSharp und JSON.NET:

public class JsonDeserializer : IDeserializer

{

public JsonDeserializer() {

this.ContentType = "application/json";

}

public string RootElement { get; set; }

public string Namespace { get; set; }

public string ContentType { get; set; }

public string DateFormat { get; set; }

public T Deserialize<T>(

IRestResponse response) {

// Deserialisierung mit JSON.NET

return JsonConvert.

DeserializeObject<T>( response.Content);

}

}

Die Klasse wird gegenüber RestSharp als Handler registriert, und schon arbeiten beide Komponenten wieder Hand in Hand:

var client = new RestClient {

BaseUrl = "http://maps.googleapis.com"

};

client.AddHandler("application/json",

new JsonDeserializer());

Fazit

Es gibt viele JSON-Bibliotheken, selbst die Framework Class Library bietet von Haus aus deren zwei. Mit JSON.NET kommt eine weitere dazu, die den eigenen Benchmarks nach den Microsoft-Implementierungen in Sachen Geschwindigkeit deutlich überlegen ist. Funktional gilt das allemal.

JSON.NET bietet eine sehr umfangreiche Unterstützung des Datenformats, verschiedene Verwendungsansätze und erlaubt den individuellen Eingriff in die Serialisierungslogik. Der hier vorgestellte Funktionsumfang gibt nur einen Teil dessen wieder, was die Bibliothek bietet. Als Ritterschlag darf angesehen werden, dass selbst Microsoft beim ASP.NET Web API JSON.NET den eigenen Implementierungen vorzieht.

Seine Stärken spielt JSON.NET bei der Serialisierung und Deserialisierung in sogenannte POCOs aus, Plain Old CLR Objects, sprich .NET-Klassen. Data-Transfer-Objekte lassen sich mit einem Aufruf zuverlässig in JSON umwandeln und wieder zurück. Wer auf externe Daten zugreift, kann für diese zum Beispiel mit den vorgestellten Werkzeugen JSON C# Class Generator und json2csharp zu verfeinernde Klassenstrukturen generieren lassen.

Man mag es konsequent nennen (das ist meine Meinung) oder auch nicht: JSON.NET bietet keinen Zugriff auf externe Ressourcen, sondern konzentriert sich voll auf das Datenformat. Der Datenaustausch wird Frameworks wie dem ASP.NET Web API oder spezialisierten Bibliotheken wie RestSharp überlassen. Zwar hat sich diese zwischenzeitlich zugunsten einer eigenen Deserialisierung von JSON.NET abgewandt, dank offener Schnittstellen lässt sich die Zusammenarbeit dennoch gewährleisten.

Zusammen bilden die Komponenten einen tollen Technologie-Stack für die Verwendung von JSON mit REST-basierten Web-Diensten.

Wie verwenden Sie JSON in Ihren C#-Applikationen? Schreiben Sie mir unter http://fb.com/Kochen.mit.Patrick.

[1] JSON.NET bei Codeplex, http://json.codeplex.com/

[2] JSON C# Class Generator, http://jsonclassgenerator.codeplex.com

[3] json2csharp, http://json2csharp.com

[4] Google Geocoding API, www.dotnetpro.de/SL1312Kochstudio1

[5] RestSharp, http://restsharp.org

 


Flexi... was?

Flexitarier! Aufgrund der oft fleischlosen Rezepte, die ich hier vorstelle, werde ich immer wieder gefragt, ob ich denn Veganer oder zumindest Vegetarier sei. Mitnichten. Ich esse gerne Fleisch, wenn auch mit zunehmend schlechtem Gewissen. Daher halte ich den Fleischkonsum gering und meide zweifelhafte Quellen. Bei uns im Ländle stehen die nächsten Kühe gerade zehn Meter entfernt. Wer braucht da noch ein argentinisches Weiderind? Teilzeitvegetarier oder Flexitarier nennt man solche Menschen wie mich, wie ich kürzlich gelernt habe. Natürlich habe ich mich gegen dieses unnötige Etikett gleich standhaft gewehrt. Wer lässt sich schon gerne in Schubladen stecken? Komisch eigentlich, wo wir doch in unserem Job genau das mit Inbrunst tun.

Feines Thai-Satay-Gemüse mit Nudeln aus dem Wok

Mischen Sie drei Esslöffel Erdnussbutter, drei Esslöffel dicke Kokosmilch (die ohne Emulgator kaufen, sie ist dicker), zwei Esslöffel Sojasauce und 50 Milliliter Wasser zu einer glatten Sauce. Für die Schärfe geben Sie Chili als Flocken oder gemahlen dazu und für die Süße einen Teelöffel Zucker. Etwas scharf-süße Chilisauce passt auch, dann lassen Sie den Zucker weg. Zum Schluss habe ich noch eine sehr großzügige Portion 5-Gewürze-Pulver dazugegeben, es besteht aus Nelke, Fenchel, Sternanis, Szechuanpfeffer und Zimt. Erschrecken Sie nicht beim Abschmecken, die salzige Sojasauce ist sehr dominant!

Schnipseln Sie Gemüse nach Wahl in mundgerechte Stücke, gerne etwas gröber. Es passen zum Beispiel ein bis zwei Paprika, jede Menge Möhren, Zucchini und Tomaten. Brokkoli-Röschen und Zuckererbsen sind auch lecker. Auf keinen Fall dürfen Sie eine große, süße Zwiebel und grob zerdrückten Knoblauch vergessen. Als letzte Vorbereitung reiben Sie etwas frischen Ingwer darüber.

Bereiten Sie nun eine gute Portion Asia-Nudeln entsprechend der Verpackung zu. Die Nudeln gibt es mit und ohne Eier, mir schmecken die ohne Eier sehr gut und sie kommen in diesem Gericht zum Einsatz.

Während die Nudeln kochen, geht’s ans Eingemachte: Geben Sie etwas Sesamöl in den Wok oder die Pfanne und schalten Sie auf maximale Hitze. Das Gemüse kommt entsprechend seiner Garzeit schrittweise dazu: Möhren, Paprika, Zucchini, Tomaten, Knoblauch und möglichst spät die Zwiebeln. Das Gemüse wird unter Rühren nur wenige Minuten angebraten, denn alles soll bissfest bleiben. Geben Sie nun die Sauce und den Ingwer dazu und lassen alles kurz aufkochen.

Jetzt sollten die Nudeln schon fertig sein: Abgießen und ab in den Wok, unterrühren, alles nochmals kurz anbraten und ab aufs Porzellan. Perfekt passt Koriandergrün dazu. Wer das nicht mag, nimmt Basilikum. Grob gehackte Erdnüsse sorgen für den Knack beim Essen. Ich hatte nur Cashews. Für einen intensiven Geschmack kommen die mit etwas Salz für 20 Minuten bei 100 Grad unter den Backofengrill. Ein langes Rezept, das umso schneller gelingt und extrem lecker schmeckt. Probieren Sie es aus! Ach ja, vegetarisch ist das Gericht allemal, und wenn Sie Nudeln ohne Eier verwenden, sogar vegan. Guten Appetit!