JSON verwerken met Kotlin en Klaxson

1. Overzicht

Klaxon is een van de open source bibliotheken die we kunnen gebruiken om JSON in Kotlin te parseren.

In deze zelfstudie gaan we naar de functies kijken.

2. Maven Afhankelijkheid

Eerst moeten we de bibliotheekafhankelijkheid toevoegen aan ons Maven-project:

 com.beust claxon 3.0.4 

De laatste versie is te vinden op jcenter of in de Spring Plugins Repository.

3. API-functies

Klaxon heeft vier API's om met JSON-documenten te werken. We zullen deze in de volgende secties onderzoeken.

4. API voor objectbinding

Met deze API we kunnen JSON-documenten aan Kotlin-objecten binden en vice versa.

Laten we om te beginnen het volgende JSON-document definiëren:

{"name": "HDD"}

Vervolgens maken we het Product klasse voor binding:

class Product (waarde naam: String)

Nu kunnen we de serialisering testen:

@Test plezier gegevenProduct_whenSerialize_thenGetJsonString () {val product = Product ("HDD") val resultaat = Klaxon (). ToJsonString (product) assertThat (resultaat) .isEqualTo ("" "{" name ":" HDD "}" "") }

En we kunnen deserialisatie testen:

@Test plezier gegevenJsonString_whenDeserialize_thenGetProduct () {val result = Klaxon (). Parse ("" "{" name ":" RAM "}" "") assertThat (resultaat? .Name) .isEqualTo ("RAM")}

Deze API ondersteunt ook het werken met dataklassen en met veranderlijke en onveranderlijke klassen.

Klaxon staat ons toe pas het mappingproces aan met de @Json annotatie. Deze annotatie heeft twee eigenschappen:

  • naam - voor het instellen van een andere naam voor de velden
  • buiten beschouwing gelaten - voor het negeren van velden van het mappingproces

Laten we een Aangepast product klas om te zien hoe deze werken:

class CustomProduct (@Json (name = "productName") val name: String, @Json (ignored = true) val id: Int)

Laten we het nu verifiëren met een test:

@Test plezier gegevenCustomProduct_whenSerialize_thenGetJsonString () {val product = CustomProduct ("HDD", 1) val resultaat = Klaxon (). ToJsonString (product) assertThat (resultaat) .isEqualTo ("" "{" productName ":" HDD "}" " ")}

Zoals we kunnen zien, is de naam eigenschap is geserialiseerd als productnaam, en de ID kaart eigenschap wordt genegeerd.

5. Streaming-API

Met de streaming-API kunnen we enorme JSON-documenten verwerken door uit een stream te lezen. Deze functie staat onze code toe om JSON-waarden te verwerken terwijl deze nog aan het lezen is.

We moeten de JsonReader class uit de API om een ​​JSON-stream te lezen. Deze klasse heeft twee speciale functies om streaming af te handelen:

  • beginObject () - zorgt ervoor dat het volgende token het begin van een object is
  • beginArray () - zorgt ervoor dat het volgende token het begin van een array is

Met deze functies kunnen we er zeker van zijn dat de stream correct is gepositioneerd en dat deze is gesloten nadat het object of de array is verbruikt.

Laten we de streaming-API testen aan de hand van een reeks van de volgende Productgegevens klasse:

dataklasse ProductData (val name: String, val capacityInGb: Int)
@Test plezier gegevenJsonArray_whenStreaming_thenGetProductArray () {val jsonArray = "" "[{" name ":" HDD "," capacityInGb ": 512}, {" name ":" RAM "," capacityInGb ": 16}]" "" val verwachteArray = arrayListOf (ProductData ("HDD", 512), ProductData ("RAM", 16)) val klaxon = Klaxon () val productArray = arrayListOf () JsonReader (StringReader (jsonArray)). gebruik {reader -> reader.beginArray {while (reader.hasNext ()) {val product = klaxon.parse (reader) productArray.add (product !!)}}} assertThat (productArray) .hasSize (2) .isEqualTo (verwachteArray)}

6. JSON Path Query API

Klaxon ondersteunt de elementlocatiefunctie van de JSON Path-specificatie. Met deze API kunnen we definieer padmatchers om specifieke vermeldingen in onze documenten te lokaliseren.

Merk op dat deze API ook streamt, en we zullen op de hoogte worden gesteld nadat een element is gevonden en geparseerd.

We moeten de PathMatcher koppel. Deze interface wordt aangeroepen wanneer het JSON-pad overeenkomsten van de reguliere expressie heeft gevonden.

Om dit te gebruiken, moeten we de methoden ervan implementeren:

  • pathMatches () - retourneer waar als we dit pad willen observeren
  • onMatch () - afgevuurd wanneer het pad is gevonden; merk op dat de waarde alleen een basistype kan zijn (bijv. int, Draad) en nooit JsonObject of JsonArray

Laten we een test maken om het in actie te zien.

Laten we eerst een JSON-inventarisdocument definiëren als een gegevensbron:

{"inventaris": {"schijven": [{"type": "HDD", "sizeInGb": 1000}, {"type": "SDD", "sizeInGb": 512}]}}

Nu implementeren we het PathMatcher interface als volgt:

val pathMatcher = object: PathMatcher {override fun pathMatches (path: String) = Pattern.matches (". * inventory. * disks. * type. *", path) override fun onMatch (path: String, value: Any) {when (pad) {"$ .inventory.disks [0] .type" -> assertThat (waarde) .isEqualTo ("HDD") "$ .inventory.disks [1] .type" -> assertThat (waarde) .isEqualTo ( "SDD")}}}

Merk op dat we de regex hebben gedefinieerd om overeen te komen met het type schijf van ons inventarisatiedocument.

Nu zijn we klaar om onze test te definiëren:

@Test plezier gegevenDiskInventory_whenRegexMatches_thenGetTypes () {val jsonString = "" "..." "" val pathMatcher = // ... Klaxon (). PathMatcher (pathMatcher) .parseJsonObject (StringReader (jsonString))}

7. API op laag niveau

Met Klaxon kunnen we JSON-documenten verwerken als een Kaart of een Lijst. Hiervoor kunnen we de lessen gebruiken JsonObject en JsonArray van de API.

Laten we een test maken om het JsonObject in actie:

@Test plezier gegevenJsonString_whenParser_thenGetJsonObject () {val jsonString = StringBuilder ("" "{" name ":" HDD "," capacityInGb ": 512," sizeInInch ": 2.5}" "") val parser = Parser () val json = parser .parse (jsonString) als JsonObject assertThat (json) .hasSize (3) .containsEntry ("name", "HDD") .containsEntry ("capacityInGb", 512) .containsEntry ("sizeInInch", 2.5)}

Laten we nu een test maken om de JsonArray functionaliteit:

@Test plezier gegevenJsonStringArray_whenParser_thenGetJsonArray () {val jsonString = StringBuilder ("" "[{" name ":" SDD "}, {" madeIn ":" Taiwan "}, {" garantieInYears ": 5}]" "") val parser = Parser () val json = parser.parse (jsonString) als JsonArray assertSoftly ({softly -> softly.assertThat (json) .hasSize (3) softly.assertThat (json [0] ["name"]). IsEqualTo (" SDD ") softly.assertThat (json [1] [" madeIn "]). IsEqualTo (" Taiwan ") softly.assertThat (json [2] [" garantieInYears "]). IsEqualTo (5)})}

Zoals we in beide gevallen kunnen zien, hebben we de conversies uitgevoerd zonder de definitie van specifieke klassen.

8. Conclusie

In dit artikel hebben we de Klaxon-bibliotheek en zijn API's onderzocht om JSON-documenten te verwerken.

Zoals altijd is de broncode beschikbaar op Github.