Skip to content

Commit

Permalink
#32 start writing JsonPath dsl
Browse files Browse the repository at this point in the history
  • Loading branch information
eld0727 committed Aug 9, 2018
1 parent 3098c97 commit 7e08802
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 0 deletions.
32 changes: 32 additions & 0 deletions modules/core/src/main/scala/tethys/readers/JsonPath.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package tethys.readers

import tethys.JsonReader
import tethys.readers.JsonPath.JsonObjectPart
import tethys.readers.instances.SingleValueObjectReader

import scala.language.dynamics


sealed trait JsonPath extends Dynamic {
def as[A](implicit reader: JsonReader[A]): JsonReader[A] = buildReader(reader)
def array()

def selectDynamic(name: String): JsonObjectPart = new JsonObjectPart(name, this)
def applyDynamic(index: Int): JsonObjectPart = ???

protected def buildReader[A](inner: JsonReader[A]): JsonReader[A]
}


object JsonPath extends JsonPath {

override protected def buildReader[A](inner: JsonReader[A]): JsonReader[A] = inner

final class JsonObjectPart(name: String, outer: JsonPath) extends JsonPath {
override protected def buildReader[A](inner: JsonReader[A]): JsonReader[A] = {
outer.buildReader(new SingleValueObjectReader[A](name, inner))
}
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package tethys.readers.instances

import tethys.JsonReader
import tethys.readers.tokens.TokenIterator
import tethys.readers.{FieldName, ReaderError}

import scala.annotation.tailrec
import scala.reflect.ClassTag

class SingleValueObjectReader[A: ClassTag](name: String, reader: JsonReader[A]) extends JsonReader[A] {


override def read(it: TokenIterator)(implicit fieldName: FieldName): A = {
if(!it.currentToken().isObjectStart) ReaderError.wrongType[A]
else readField(it)
}

@tailrec
private def readField(it: TokenIterator)(implicit fieldName: FieldName): A = {
it.currentToken() match {
case token if token.isObjectEnd =>
it.nextToken()
reader.defaultValue.getOrElse(ReaderError.wrongJson(s"'$name' field is missing"))
case token if token.isFieldName =>
val currentName = it.fieldName()
it.nextToken()
if(currentName == name) {
val res = reader.read(it)(fieldName.appendFieldName(name))
skipRest(it)
res
} else {
readField(it)
}

case token => ReaderError.wrongJson(s"Expect end of object or field name but '$token' found")
}
}

@tailrec
private def skipRest(it: TokenIterator)(implicit fieldName: FieldName): Unit = {
it.currentToken() match {
case token if token.isObjectEnd =>
it.nextToken()

case token if token.isFieldName =>
it.nextToken()
it.skipExpression()
skipRest(it)

case token =>
ReaderError.wrongJson(s"Expect end of object or field name but '$token' found")
}
}
}

0 comments on commit 7e08802

Please sign in to comment.