2016-06-21 24 views
2

Angenommen, das folgende einfache JSON-Dokument:Wie ändert man den Wert und gibt JSON mit dem Argonaut-Objektiv ein?

 { 
     "key" : "val1" 
     } 

Ich mag würde den Wert des „Schlüssels“ aktualisieren, aber zugleich auch seine Art ändern, so von Zeichenkette, die es in ein int ändern. Nun, wie ein HCURSOR mit unten ist es möglich, und gerade nach vorne, es zu tun:

val cursor = js.hcursor 
val position = (cursor --\ "key") >-> (_ => jNumber(1)) 

Mit „Verhängnis“ die obige Position ich ein neues json am Ende mit dem „Schlüssel“ einen numerischen Wert hat und nicht einen String Das ist perfekt.

Ist es möglich, dasselbe mit Linsen zu tun? Ich habe versucht, die folgenden Funktionen ausführen:

val lense = jObjectPL >=> 
      jsonObjectPL("key") >=> 
      jNumberPL 
lense.mod(_ => JsonBigDecimal(1), js) 

Aber obwohl ich es nicht einen Fehler auch nicht, ich unmodifizierten am Ende mit dem ursprünglichen json Dokument am Ende nicht funktioniert. Wenn ich jedoch den Datentyp respektiere, funktionieren die Dinge so, wie sie sollten. Gibt es einen Grund, dass Objektive nur für Änderungen desselben Datentyps verwendet werden sollten? Oder ich mache gerade etwas schrecklich falsch :)

Antwort

4

Nein, nichts ist schrecklich falsch-du bist fast da. Das Problem ist, dass dieser Weg:

jObjectPL >=> jsonObjectPL("key") >=> jNumberPL 

navigiert zu einer JSON Anzahl an "key". Ihre js hat keine JSON-Nummer in der Taste, so dass das Objektiv auf nichts zeigt und die Änderung nichts beeinflusst.

Sie können dieses Problem beheben, indem nur den letzten Schritt von der Linse zu entfernen:

val lens = jObjectPL >=> jsonObjectPL("key") 

Dieses navigiert nur auf das "key" Feld aber nicht setzt Einschränkungen nicht auf welcher Art von JSON-Wert ist. Dann können Sie ihn ändern, was Sie wollen:

scala> val lens = jObjectPL >=> jsonObjectPL("key") 
lens: scalaz.PLensFamily[... 

scala> lens.mod(_ => jNumber(JsonBigDecimal(1)), js) 
res0: argonaut.Json = {"key":1} 

Beachten Sie, dass, da die Linse auf einen Json Wert zeigt, kein JsonNumber, werden Sie die JsonBigDecimal in jNumber wickeln müssen die Typen machen ausrichten.

+0

Danke für die schnelle Antwort @Travis! sehr geschätzt. Beim Lesen der Dokumentation für Objektive & Argonaut hatte ich den Eindruck, dass Sie immer den JSON-Datentyp definieren sollten, den Sie erwarten. Aber ich denke, es ist ein Teil der menschlichen Natur, Dinge manchmal zu komplizieren :) – cpard

+0

@cpard Yep :). In diesem Fall erwarten Sie eine JSON-Zeichenfolge an dieser Position, aber wenn Sie dem Objektiv "jStringPL" hinzufügen, können Sie diesen Typ nicht ändern. –