jrudolph / json-lenses Goto Github PK
View Code? Open in Web Editor NEWA library to query and update JSON data in Scala.
License: Apache License 2.0
A library to query and update JSON data in Scala.
License: Apache License 2.0
When using JSON-Lenses within Spray-routing, I get the following error:
[error] found : Symbol
[error] required: ?{def ?: ?}
[error] Note that implicit conversions are not applicable because they are ambiguous:
[error] both method symbol2NR in trait ToNameReceptaclePimps of type (symbol: Symbol)spray.routing.directives.NameReceptacle[String]
[error] and method strToPossiblyOptionalField in object JsonLenses of type (sym: Symbol)spray.json.lenses.JsonLenses.OptionalFieldBuilder
[error] are possible conversion functions from Symbol to ?{def ?: ?}
[error] {json.extract[String]('parties / 'person / filter('id.is[String](_ == id)) / 'firstName)}{json.extract[String]('parties / 'person / filter('id.is[String](_ == id)) / 'lastName)}{json.extract[String]('parties / 'person / filter('id.is[String](_ == id)) / 'organisationName.?).headOption match {
I'm trying to construct a JSON object using multple JsonPath expressions and values extracted from different sources. The following snippet reproduces the problem I'm facing. Namely, the set operation doesn't work on JsonPath expressions. json.update('object_id ! set(1))
works as expected.
val json = JsObject()
val lens = JsonLenses.fromPath("$.object_id")
val updated = json.update(lens ! set(1))
In this case updated
will be an empty object.
Any plans to crossbuild for 2.12?
I'm just getting started using this library and I'm running into a requirement to support both field renames and field mappers.
One step further would be to be able to completely map a field in both its name and its value (including its type), i.e. being able to write a simple conversion from {foo: 42)
to {bar: {baz: 42}}
(so using the old value but wrapping it in some new structure with a new key)
The way I currently implement these cases is by using a combination of an extract and a set. Of course this does mean that the old field will still be present.
Do you think it is possible to implement this with the current codebase or would it require a major redesign? I haven't really dived into the implementation yet but if you would give some hints I might be able to come up with a pull request.
The implementation of getOrThrow wraps the Throwable in Left inside a RuntimeException. Wouldn't it be more convenient to throw the Throwable directly? That way one could simply catch DeserializationError instead of catching RuntimeException and check if it contains a DeserializationError.
When trying to write a nested js:
{"a" : { "b" : "c"}}
using a single lens
val ab = 'a / 'b
JsObject.update(ab ! set("c"))
That fails.
So far I solved this with a rather poor solution, another combining operator:
trait EskoLenses extends ScalarLenses with OptionLenses with SeqLenses with Operations with JsonPathIntegration with ExtraImplicits {
def writeIfAbscentCombine[M[_], M2[_], R[_]](outer: Lens[M], inner: Lens[M2])(implicit ev: Join[M2, M, R]): Lens[R] =
new LensImpl[R]()(ev.get(inner.ops, outer.ops)) {
def retr: JsValue => Validated[R[JsValue]] = parent =>
for {
outerV <- outer.retr(parent)
innerV <- ops.allRight(outer.ops.flatMap(outerV)(x => inner.ops.toSeq(inner.retr(x))))
} yield innerV
def updated(f: SafeJsValue => SafeJsValue)(parent: JsValue): SafeJsValue =
outer.updated {
case l: Left[_, _] =>
inner.updated(f)(JsObject())
case r @ Right(js) =>
inner.updated(f)(js)
}(parent)
}
}
object EskoLenses extends EskoLenses {
implicit class WriteIfAbscenCombinator(outer: ScalarLens) {
/**
* When using this operator, the resulting lens join will not fail when trying to to do inner level writes, it will instead initialize an empty object
*
* @param inner
* @return
*/
def /?(inner: ScalarLens): ScalarLens = {
EskoLenses.writeIfAbscentCombine(outer, inner)
}
}
}
I'm sure better solutions could be thought of.
E.g. a combining lens could be a class which can be matched against and from which the inner and outer can be recovered. That way the need for parent node creation could be detected and executed before attempting to write the nested json.
I encountered an interesting situation where optional fields does not address to solve this problem
val json = JsonParser(
"""
{
"host" : {
"name" : "disposable-cluster-05.cphy.local",
"config" : {
"storageDevice" : {
"scsiLun" : [
{
"uuid" : "0005000000766d68626133323a303a30",
"lunType" : "cdrom"
},
{
"capacity" : {
"blockSize" : 512,
"block" : 1048576000
},
"devicePath" : "/vmfs/devices/disks/naa.6000c2914633a6cf3c6b48a67089ca09",
"ssd" : false,
"uuid" : "02000000006000c2914633a6cf3c6b48a67089ca09566972747561",
"lunType" : "disk"
},
{
"capacity" : {
"blockSize" : 512,
"block" : 8388608
},
"devicePath" : "/vmfs/devices/disks/mpx.vmhba1:C0:T0:L0",
"ssd" : false,
"uuid" : "0000000000766d686261313a303a30",
"lunType" : "disk"
}
]
}
}
}
}
""".stripMargin)
json.extractBoolean)
res12: Seq[Boolean] = List(false, false)
The result returned is 2 elements (rightfully) as the first element of the array is missing for valid reasons.
Now there is a positional implication in this extraction, since 2 elements are returns (subscript (1),(2) and not (0)) ...
How will I align these two elements with other elements that I extract from this Array ?
Is it possible to receive a List("",false,false) instead of List(false,false)... ?
I'd be good if JSON-lenses could cope with
If I have a field which may be null then it blows up on extraction:
val json = """{ "url": null }""".parseJson
json.extract[String]("url".?)
This causes a runtime exception with root cause:
spray.json.DeserializationException: Expected String as JsString, but got null
Is this an issue with son-lenses, or am I doing something wrong (a strong possibility)?
Hi,
if you run following snippet parsing json you will get stackoverflow error:
Exception in thread "main" java.lang.StackOverflowError
at spray.json.lenses.Ops$$anon$3.spray$json$lenses$Ops$$anon$$inner$1(Ops.scala:63)
at spray.json.lenses.Ops$$anon$3$$anonfun$spray$json$lenses$Ops$$anon$$inner$1$1.apply(Ops.scala:67)
at spray.json.lenses.Ops$$anon$3$$anonfun$spray$json$lenses$Ops$$anon$$inner$1$1.apply(Ops.scala:66)
at scala.util.Either$RightProjection.flatMap(Either.scala:522)
at spray.json.lenses.Ops$$anon$3.spray$json$lenses$Ops$$anon$$inner$1(Ops.scala:66)
at spray.json.lenses.Ops$$anon$3$$anonfun$spray$json$lenses$Ops$$anon$$inner$1$1.apply(Ops.scala:67)
at spray.json.lenses.Ops$$anon$3$$anonfun$spray$json$lenses$Ops$$anon$$inner$1$1.apply(Ops.scala:66)
at scala.util.Either$RightProjection.flatMap(Either.scala:522)
at spray.json.lenses.Ops$$anon$3.spray$json$lenses$Ops$$anon$$inner$1(Ops.scala:66)
at spray.json.lenses.Ops$$anon$3$$anonfun$spray$json$lenses$Ops$$anon$$inner$1$1.apply(Ops.scala:67)
at spray.json.lenses.Ops$$anon$3$$anonfun$spray$json$lenses$Ops$$anon$$inner$1$1.apply(Ops.scala:66)
at scala.util.Either$RightProjection.flatMap(Either.scala:522)
object SO extends App {
import spray.json.lenses.JsonLenses._
import spray.json.DefaultJsonProtocol._
val lens = 'aggregations / 'unique_values / 'buckets / * / 'key
val bucket = List.fill(3000)("""{"key": 123456789,"doc_count": 1}""")
val json =
s"""
|{
| "took": 53,
| "timed_out": false,
| "_shards": {
| "total": 5,
| "successful": 5,
| "failed": 0
| },
| "hits": {
| "total": 11581,
| "max_score": 0.0,
| "hits": [
|
| ]
| },
| "aggregations": {
| "unique_values": {
| "doc_count_error_upper_bound": 0,
| "sum_other_doc_count": 0,
| "buckets": [
| ${bucket.mkString(",")}
| ]
| }
| }
|}
""".stripMargin
println(json.extract[Long](lens))
}
For me it fails on 'bucket containing about 2100 elements, which is not actually that big value I suppose. Everything below works quite well.
Cheers,
Maciek
json-lenses fails with the following JSON:
{"parties": {
"@size": "4",
"organisation": [
{
"id": "19529848",
"contacts": {
"address": {
"id": "36692152",
"street": "Winchester Road",
"city": "Leicester",
"state": "Leicestershire",
"zip": "LE8 5PR",
"country": "United Kingdom"
},
"email": {
"id": "38472610",
"emailAddress": "[email protected]"
},
"phone": {
"id": "36692153",
"type": "Work",
"phoneNumber": "0116 2771555"
},
"website": [
{
"id": "36692154",
"webAddress": "01162771555",
"webService": "SKYPE",
"url": "skype:01162771555"
},
{
"id": "36692155",
"webAddress": "http:\/\/www.countesthorpe.leics.sch.uk\/",
"webService": "URL",
"url": "http:\/\/www.countesthorpe.leics.sch.uk\/"
},
{
"id": "44805492",
"webAddress": "countesthorpecc",
"webService": "TWITTER",
"url": "http:\/\/twitter.com\/countesthorpecc"
}
]
},
"pictureURL": "https:\/\/facehub.appspot.com\/twitter\/countesthorpecc?size=70",
"createdOn": "2012-01-26T17:02:20Z",
"updatedOn": "2012-04-22T21:42:21Z",
"name": "Countesthorpe Community College"
},
{
"id": "19529389",
"contacts": {
"address": {
"id": "36690382",
"street": "Roman Road",
"city": "Stockbridge",
"state": "Hampshire",
"zip": "SO20 6HA",
"country": "United Kingdom"
},
"email": {
"id": "42953581",
"emailAddress": "[email protected]"
},
"phone": {
"id": "36690383",
"type": "Work",
"phoneNumber": "01264 810555"
},
"website": [
{
"id": "36690384",
"webAddress": "01264810555",
"webService": "SKYPE",
"url": "skype:01264810555"
},
{
"id": "36690385",
"webAddress": "http:\/\/www.testvalley.hants.sch.uk",
"webService": "URL",
"url": "http:\/\/www.testvalley.hants.sch.uk"
},
{
"id": "45433587",
"webAddress": "testvalleysch",
"webService": "TWITTER",
"url": "http:\/\/twitter.com\/testvalleysch"
}
]
},
"pictureURL": "https:\/\/facehub.appspot.com\/twitter\/testvalleysch?size=70",
"createdOn": "2012-01-26T16:55:30Z",
"updatedOn": "2012-05-01T14:37:19Z",
"name": "Test Valley School"
},
{
"id": "19529442",
"contacts": {
"address": {
"id": "36690619",
"street": "Micheldever Road",
"city": "Whitchurch",
"state": "Hampshire",
"zip": "RG28 7JF",
"country": "United Kingdom"
},
"email": {
"id": "38202053",
"emailAddress": "[email protected]"
},
"phone": {
"id": "36690621",
"type": "Work",
"phoneNumber": "01256 892061"
},
"website": [
{
"id": "36690622",
"webAddress": "01256892061",
"webService": "SKYPE",
"url": "skype:01256892061"
},
{
"id": "36690623",
"webAddress": "http:\/\/www.testbourne.hants.sch.uk",
"webService": "URL",
"url": "http:\/\/www.testbourne.hants.sch.uk"
}
]
},
"pictureURL": "https:\/\/d365sd3k9yw37.cloudfront.net\/a\/1374761982\/theme\/default\/images\/org_avatar_70.png",
"createdOn": "2012-01-26T16:56:25Z",
"updatedOn": "2012-03-28T07:49:50Z",
"name": "Testbourne Community School"
},
{
"id": "19532674",
"contacts": {
"address": {
"id": "36705515",
"street": "Testwood Lane",
"city": "Southampton",
"state": "Hampshire",
"zip": "SO40 3ZW",
"country": "United Kingdom"
},
"email": {
"id": "49311759",
"emailAddress": "[email protected]"
},
"phone": {
"id": "36705516",
"type": "Work",
"phoneNumber": "023 80862146"
},
"website": [
{
"id": "36705517",
"webAddress": "02380862146",
"webService": "SKYPE",
"url": "skype:02380862146"
},
{
"id": "36705519",
"webAddress": "http:\/\/www.testwood.hants.sch.uk",
"webService": "URL",
"url": "http:\/\/www.testwood.hants.sch.uk"
}
]
},
"pictureURL": "https:\/\/d365sd3k9yw37.cloudfront.net\/a\/1374761982\/theme\/default\/images\/org_avatar_70.png",
"createdOn": "2012-01-26T17:29:34Z",
"updatedOn": "2012-06-20T09:10:42Z",
"name": "Testwood Sports College"
}
]
}}
Trace:
size: 4 index: 4
at spray.json.lenses.package$GetOrThrow.getOrThrow(package.scala:24) ~[json-lenses_2.10-0.5.3.jar:0.5.3]
at spray.json.lenses.LensImpl.get(Lens.scala:33) ~[json-lenses_2.10-0.5.3.jar:0.5.3]
at spray.json.lenses.ExtraImplicits$RichJsValue$class.extract(ExtraImplicits.scala:16) ~[json-lenses_2.10-0.5.3.jar:0.5.3]
at spray.json.lenses.ExtraImplicits$$anon$1.extract(ExtraImplicits.scala:28) ~[json-lenses_2.10-0.5.3.jar:0.5.3]
at uk.co.coen.ciscoipphonedir.CapsuleCRMCiscoIPPhoneDirectoryService$$anonfun$receive$1$$anonfun$applyOrElse$1$$anonfun$2.apply(CapsuleCRMCiscoIPPhoneDirectoryService.scala:117) ~[classes/:na]
at uk.co.coen.ciscoipphonedir.CapsuleCRMCiscoIPPhoneDirectoryService$$anonfun$receive$1$$anonfun$applyOrElse$1$$anonfun$2.apply(CapsuleCRMCiscoIPPhoneDirectoryService.scala:117) ~[classes/:na]
at scala.collection.TraversableLike$WithFilter$$anonfun$map$2.apply(TraversableLike.scala:722) ~[scala-library.jar:0.12.0]
at scala.collection.immutable.Range.foreach(Range.scala:141) ~[scala-library.jar:0.12.0]
at scala.collection.TraversableLike$WithFilter.map(TraversableLike.scala:721) ~[scala-library.jar:0.12.0]
I am faced with the fact that some operations are not currently supported in JsonPath.
I have query like this:
$.[?(@.id=='1' && @.name == 'Pasha')]
I see that this project has not been updated for a long time... Do you have any plans to support this project?
From http://pastie.org/6611121:
import spray.json.lenses._
import spray.json.{JsValue, JsonParser, DefaultJsonProtocol}
import JsonLenses._
import DefaultJsonProtocol._
import JsonLenses.fromPath
val str = """{"host":{"name":"svr-mam-vm-05.mam.mentorg.com","config":{"fileSystemVolume":{"mountInfo":[{"volume":{"extent":[{"partition":5,"diskName":"naa.600508e0000000009e2ce98ad02b3203"}]}},{"volume":{}},{"volume":{}},{"volume":{}},{"volume":{}},{"volume":{}}]}}}}"""
val json = JsonParser(str)
val diskNameXpathQuery = "$.host.config.fileSystemVolume.mountInfo[*].volume.extent[*].diskName"
val partitionXpathQuery = "$.host.config.fileSystemVolume.mountInfo[*].volume.extent[*].partition"
val diskName = json.extract[String](fromPath(diskNameXpathQuery))
val partition = json.extract[String](fromPath(partitionXpathQuery))
Based on the structure above where some of the "volume" elements in the array are empty, causing an exception rather than an graceful set to null
java.lang.RuntimeException: Expected field 'extent' in '{}'
at spray.json.lenses.package$.unexpected(package.scala:16)
at spray.json.lenses.package$ValidateOption.getOrError(package.scala:51)
at spray.json.lenses.ScalarLenses$$anon$1$$anonfun$retr$1$$anonfun$apply$1.apply(ScalarLenses.scala:15)
at spray.json.lenses.ScalarLenses$$anon$1$$anonfun$retr$1$$anonfun$apply$1.apply(ScalarLenses.scala:15)
at scala.util.Either$RightProjection.flatMap(Either.scala:523)
at spray.json.lenses.ScalarLenses$$anon$1$$anonfun$retr$1.apply(ScalarLenses.scala:14)
at spray.json.lenses.ScalarLenses$$anon$1$$anonfun$retr$1.apply(ScalarLenses.scala:14)
at spray.json.lenses.JsonLenses$$anon$1$$anonfun$retr$1.apply(JsonLenses.scala:26)
at spray.json.lenses.JsonLenses$$anon$1$$anonfun$retr$1.apply(JsonLenses.scala:24)
at spray.json.lenses.JsonLenses$$anon$1$$anonfun$retr$1$$anonfun$apply$1$$anonfun$apply$2.apply(JsonLenses.scala:27)
at spray.json.lenses.JsonLenses$$anon$1$$anonfun$retr$1$$anonfun$apply$1$$anonfun$apply$2.apply(JsonLenses.scala:27)
at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:251)
at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:251)
at scala.collection.immutable.List.foreach(List.scala:309)
at scala.collection.TraversableLike$class.flatMap(TraversableLike.scala:251)
I'm iterating over an array where each element is a map, and I need a field from each nested map. The key may be present in some maps but absent in others. How can this be expressed in your lens syntax? I'd naturally expect an Option type on the result.
The Apache 2.0 license requires the author to place a copyright notice in the source. I did not find such.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
This makes it more difficult to attribute your project correctly. I would suggest to check some other Apache 2.0 project and see how they claim copyright. To me, a notion anywhere within say README.md
(either beginning or the very end, where license is mentioned) would be sufficient.
Addendum:
In fact, the README.md currently says:
spray-json is licensed under APL 2.0.
Copy-paste error. Should say json-lenses
.
See this transcript:
scala> val jsonResult = """{
"books": [
{
"title": "The Space Merchants",
"price": "10.99"
},
{
"title": "Dune",
"price": "8.95"
}
]
}""".asJson
jsonResult: spray.json.JsValue = {"books":[{"title":"The Space Merchants","price":"10.99"},{"title":"Dune","price":"8.95"}]}
scala> jsonResult.extract[String](fromPath("$.books[?(@.title=='The Space Merchants')].price"))
Results in the following exception.
org.parboiled.errors.ParsingException: Invalid JSON source:
Invalid input 'S', expected ' ', '\n', '\r', '\t', '\f', '<', '>', "==" or ')' (line 1, pos 25):
$.books[?(@.title=='The Space Merchants')].price
^
at spray.json.lenses.JsonPathParser$$anonfun$apply$8.apply(JsonPathParser.scala:89)
at spray.json.lenses.JsonPathParser$$anonfun$apply$8.apply(JsonPathParser.scala:89)
at scala.Option.getOrElse(Option.scala:120)
at spray.json.lenses.JsonPathParser$.apply(JsonPathParser.scala:88)
at spray.json.lenses.JsonPathParser$.apply(JsonPathParser.scala:81)
at spray.json.lenses.JsonPathIntegration$class.fromPath(JsonPathIntegration.scala:9)
at spray.json.lenses.JsonLenses$.fromPath(JsonLenses.scala:8)
See https://groups.google.com/d/topic/spray-user/PmthphJUr5s/discussion
I encountered an interesting situation where optional fields does not address to solve this problem
val json = JsonParser(
"""
{
"host" : {
"name" : "disposable-cluster-05.cphy.local",
"config" : {
"storageDevice" : {
"scsiLun" : [
{
"uuid" : "0005000000766d68626133323a303a30",
"lunType" : "cdrom"
},
{
"capacity" : {
"blockSize" : 512,
"block" : 1048576000
},
"devicePath" : "/vmfs/devices/disks/naa.6000c2914633a6cf3c6b48a67089ca09",
"ssd" : false,
"uuid" : "02000000006000c2914633a6cf3c6b48a67089ca09566972747561",
"lunType" : "disk"
},
{
"capacity" : {
"blockSize" : 512,
"block" : 8388608
},
"devicePath" : "/vmfs/devices/disks/mpx.vmhba1:C0:T0:L0",
"ssd" : false,
"uuid" : "0000000000766d686261313a303a30",
"lunType" : "disk"
}
]
}
}
}
}
""".stripMargin)
The result returned is 2 elements (rightfully) as the first element of the array is missing for valid reasons.
> json.extract[Boolean]("host" / "config" / "storageDevice" / "scsiLun" / * / optionalField("ssd"))
res12: Seq[Boolean] = List(false, false)
Now there is a positional implication in this extraction, since 2 elements are returns (subscript (1),(2) and not (0)) ...
How will I align these two elements with other elements that I extract from this Array ?
Is it possible to receive a List("default value if missing",false,false) in subscript(0) of the array element ... ?
It would be nice to access multiple fields like this:
("a", "b", "c").tryGet[(A, B, C)](json)
The current way, unless I'm missing something, has a lot of repetition:
for {
a <- "a".tryGet[A](json)
b <- "b".tryGet[B](json)
c <- "c".tryGet[C](json)
} yield (a, b, c)
Attempting to extract a Seq[Seq[String]] from this document
val json = JsonParser("""{
"vmaz" : {
"a" : {
"b" : [
{
"c" : {
"d" : [
{
"name" : "[Internal RAID10] 123",
"datastoreId" : "datastore-66",
"sizeInBytes" : 6443746134
},
{
"name" : "[Internal RAID10] 456",
"datastoreId" : "datastore-66",
"sizeInBytes" : 0
},
{
"name" : "[Internal RAID10] 789",
"datastoreId" : "datastore-66",
"sizeInBytes" : 25769803776
},
{
"name" : "[Internal RAID10] 111",
"datastoreId" : "datastore-66",
"sizeInBytes" : 0
},
{
"name" : "[Internal RAID10] 123",
"datastoreId" : "datastore-66",
"sizeInBytes" : 3615490048
}
]
}
},
{
"c" : {
"d" : [
{
"name" : "11aa",
"datastoreId" : "datastore-66",
"sizeInBytes" : 6443746148
},
{
"name" : "22aa",
"datastoreId" : "datastore-66",
"sizeInBytes" : 0
},
{
"name" : "33aa",
"datastoreId" : "datastore-66",
"sizeInBytes" : 1006686208
},
{
"name" : "44aa",
"datastoreId" : "datastore-66",
"sizeInBytes" : 0
},
{
"name" : "55aa",
"datastoreId" : "datastore-66",
"sizeInBytes" : 413696
}
]
}
},
{
"c" : {
"d" : [
{
"name" : "66aaa",
"datastoreId" : "datastore-66",
"sizeInBytes" : 6443746148
},
{
"name" : "77aaa",
"datastoreId" : "datastore-66",
"sizeInBytes" : 0
},
{
"name" : "88aaaa",
"datastoreId" : "datastore-66",
"sizeInBytes" : 15451869184
},
{
"name" : "999aaa",
"datastoreId" : "datastore-66",
"sizeInBytes" : 0
},
{
"name" : "10900assas",
"datastoreId" : "datastore-66",
"sizeInBytes" : 17190912
}
]
}
}
]
}
}
}""")
json.extract[Seq[Seq[String]]](fromPath("$.vm.a.b[*].c.d[*].name"))
I attempted other combinations and realized that it seems to be flattening it to a Seq[String]. I wouldn't want this but rather a Seq[Seq[String]] in order to preserve the alignment.
Hi ,
I have a scenario in my application , where i have to recusrively get all the data, and i tried to use the jsonPath $.store.book[*].subBooks[*]..author
as mentioned in http://goessner.net/articles/JsonPath/ . But i am getting an error while parsing. I tested the same using some online parsers and it is working fine. I would like to know if this is the right syntax to be used in JsonLenses. Please let me know if am missing some thing.
{
"store": {
"book": [
{ "category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95,
"subBooks": [
{ "category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99,
"isbn": "0-553-21311-3",
"subBooks": [
{ "category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99,
"isbn": "0-553-21311-3"
}
]
}
]
},
{ "category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99,
"isbn": "0-553-21311-3"
}
],
"bicycle": {
"color": "red",
"price": 19.95
}
}
}
Regards
Johns
for both reading and writing
Could you please let me know if I might be missing a step here
The extraction seems to be failing
Hi! Just wondering, any plans to build an upgraded version of the lib? (to use most recent versions of scala and spray)
When i try;
val authorNames = json.extract {String} (allAuthors)
i get:
error: could not find implicit value for evidence parameter of type cc.spray.json.lenses.package.Reader{String}
When i try:
val newJson1 = json.update(allAuthors ! set {String} ("John Doe"))
i get:
error: Cannot find JsonWriter or JsonFormat type class for String
// i must replaced [ with { because with [ i cant add properly msg
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.