Procesador JSON moderno

¿Le gustaría analizar ndjson en la terminal de esta manera?





where { bool("muted") } max { long("size") } top 3

{"id":4880123,"size":245,"muted":true}
{"id":2392636,"size":107,"muted":true}
{"id":15843320,"size":59,"muted":true}
      
      



En nuestro trabajo, a menudo usamos descargas en formato ndjson. Sin embargo, su análisis es difícil debido a que la herramienta estándar para esto es jq con su monstruosa sintaxis que genera lo siguiente:





cat file.ndjson | jq '.tickets | map(select(.assigned_displayname=="MyNameOnApi"))' | jq '.[] | "\(.id) \(.title) \t \(.description)\n"' | sed #some after jq prettifying 
      
      



Como no me gusta, decidí hacer un procesador json moderno con un DSL legible. ¿Qué hace ya esta herramienta?





En primer lugar, hay cinco construcciones de control similares a sql disponibles para su procesamiento:





where { /*   */ }
order { /*     */ }
min   { /*      */ }
max   { /*       */ }
top   ( /* ,    */ )
      
      



, . Kotlin, . json'. , .





5 json. :





max { long("size") } top 3 where { bool("active") },

top(5) where { !bool("active") } min { int("some") },

top(5) min { time("first") to time("last") }, // duration

where { get("arr") int (0) > 5 },

where { !get("broken") } top 3 min { get(4) get("nested") bool("flag") }
      
      



, json . , jackson:





//    jackson ,  :
get(name: String)
get(idx: String)

//       :
bool(name: String)
bool(idx: String)
int(name: String)
int(idx: String)
double(name: String)
double(idx: String)
string(name: String)
string(idx: String)
time(name: String)
time(idx: String)
      
      



?

Docker. . , . , ~/Desktop



example.ndjson



, :





docker run -v ~/Desktop:/opt -it demidko/analyze example.ndjson
      
      



! json .





dsl-, . Kotlin Kotlin . jsr223 .

, :





typealias Query = (MutableList<JsonNode>, JsonNode) -> Unit

class Action(val action: MutableList<JsonNode>.(JsonNode) -> Unit) :
  Query by { list, el ->
    list.action(el)
  }
  
infix fun Action.top(limit: Int) = Action {
  action(it)
  while (size > limit) {
    removeLast()
  }
}

fun order(comparator: Comparator<JsonNode>) = Action {
  add(it)
  sortWith(comparator)
}

infix fun Action.where(filter: JsonNode.() -> Boolean) = Action {
  if (it.filter()) {
    action(it)
  }
}
      
      



, , .





GitHub: https://github.com/demidko/analyze





! .








All Articles