- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我有一个具有以下结构的 JSON(真实世界的例子在这里 https://gist.github.com/PavelPenkov/3432fe522e02aa3a8a597020d4ee7361 ):
{
"metadata": { /* Huge TYPED object */ },
"payload": { /* Small flat UNTYPED object */
"field_1": 1
"field_2": "Alice"
}
}
我想尽快提取 payload
部分,文件很大,将其解析为案例类相当慢(在我的笔记本电脑上为 5000 op/s)。到目前为止,我已经尝试过了
用 Jackson 将整个文档解析为案例类。
使用 Jackson 解析为 AST 并仅提取 payload
字段 - 速度稍快。
scala-jsoniter
虽然它可能可以更快地解析类型化部分,但它无法按设计解析非类型化字段。
是否有任何其他选项可以从 Java 或(最好)Scala 访问?
最佳答案
跳过不需要的 JSON 值是 jsoniter-scala 的亮点。是的,它不为 JSON 提供 AST 模型,但您可以自己构建它或使用第三方库提供的模型。以下是 circe AST 的自定义编解码器示例:
package io.circe
import java.util
import com.github.plokhotnyuk.jsoniter_scala.core._
import io.circe.Json._
object CirceJsoniter {
implicit val codec: JsonValueCodec[Json] = new JsonValueCodec[Json] {
override def decodeValue(in: JsonReader, default: Json): Json = {
var b = in.nextToken()
if (b == 'n') in.readNullOrError(default, "expected `null` value")
else if (b == '"') {
in.rollbackToken()
new JString(in.readString(null))
} else if (b == 'f' || b == 't') {
in.rollbackToken()
if (in.readBoolean()) Json.True
else Json.False
} else if ((b >= '0' && b <= '9') || b == '-') {
new JNumber({
in.rollbackToken()
in.setMark() // TODO: add in.readNumberAsString() to Core API of jsoniter-scala
try {
do b = in.nextByte()
while (b >= '0' && b <= '9')
} catch { case _: JsonReaderException => /* ignore end of input error */} finally in.rollbackToMark()
if (b == '.' || b == 'e' || b == 'E') new JsonDouble(in.readDouble())
else new JsonLong(in.readLong())
})
} else if (b == '[') {
new JArray(if (in.isNextToken(']')) Vector.empty
else {
in.rollbackToken()
var x = new Array[Json](4)
var i = 0
do {
if (i == x.length) x = java.util.Arrays.copyOf(x, i << 1)
x(i) = decodeValue(in, default)
i += 1
} while (in.isNextToken(','))
(if (in.isCurrentToken(']'))
if (i == x.length) x
else java.util.Arrays.copyOf(x, i)
else in.arrayEndOrCommaError()).to[Vector]
})
} else if (b == '{') {
new JObject(if (in.isNextToken('}')) JsonObject.empty
else {
val x = new util.LinkedHashMap[String, Json]
in.rollbackToken()
do x.put(in.readKeyAsString(), decodeValue(in, default))
while (in.isNextToken(','))
if (!in.isCurrentToken('}')) in.objectEndOrCommaError()
JsonObject.fromLinkedHashMap(x)
})
} else in.decodeError("expected JSON value")
}
override def encodeValue(x: Json, out: JsonWriter): Unit = x match {
case JNull => out.writeNull()
case JString(s) => out.writeVal(s)
case JBoolean(b) => out.writeVal(b)
case JNumber(n) => n match {
case JsonLong(l) => out.writeVal(l)
case _ => out.writeVal(n.toDouble)
}
case JArray(a) =>
out.writeArrayStart()
a.foreach(v => encodeValue(v, out))
out.writeArrayEnd()
case JObject(o) =>
out.writeObjectStart()
o.toIterable.foreach { case (k, v) =>
out.writeKey(k)
encodeValue(v, out)
}
out.writeObjectEnd()
}
override def nullValue: Json = Json.Null
}
}
另一种选择,如果您只需要提取有效载荷值的字节,那么您可以使用这样的代码以每秒约 300000 条消息的速率为提供的示例执行此操作:
import com.github.plokhotnyuk.jsoniter_scala.core._
import com.github.plokhotnyuk.jsoniter_scala.macros._
import java.nio.charset.StandardCharsets.UTF_8
import java.util.concurrent.TimeUnit
import org.openjdk.jmh.annotations._
import scala.reflect.io.Streamable
import scala.util.hashing.MurmurHash3
case class Payload private(bs: Array[Byte]) {
def this(s: String) = this(s.getBytes(UTF_8))
override lazy val hashCode: Int = MurmurHash3.arrayHash(bs)
override def equals(obj: Any): Boolean = obj match {
case that: Payload => java.util.Arrays.equals(bs, that.bs)
case _ => false
}
override def toString: String = new String(bs, UTF_8)
}
object Payload {
def apply(s: String) = new Payload(s.getBytes)
implicit val codec: JsonValueCodec[Payload] = new JsonValueCodec[Payload] {
override def decodeValue(in: JsonReader, default: Payload): Payload = new Payload(in.readRawValAsBytes())
override def encodeValue(x: Payload, out: JsonWriter): Unit = out.writeRawVal(x.bs)
override val nullValue: Payload = new Payload(new Array[Byte](0))
}
}
case class MessageWithPayload(payload: Payload)
object MessageWithPayload {
implicit val codec: JsonValueCodec[MessageWithPayload] = JsonCodecMaker.make(CodecMakerConfig())
val jsonBytes: Array[Byte] = Streamable.bytes(getClass.getResourceAsStream("debezium.json"))
}
@State(Scope.Thread)
@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Fork(value = 1, jvmArgs = Array(
"-server",
"-Xms2g",
"-Xmx2g",
"-XX:NewSize=1g",
"-XX:MaxNewSize=1g",
"-XX:InitialCodeCacheSize=512m",
"-XX:ReservedCodeCacheSize=512m",
"-XX:+UseParallelGC",
"-XX:-UseBiasedLocking",
"-XX:+AlwaysPreTouch"
))
@BenchmarkMode(Array(Mode.Throughput))
@OutputTimeUnit(TimeUnit.SECONDS)
class ExtractPayloadReading {
@Benchmark
def jsoniterScala(): MessageWithPayload = readFromArray[MessageWithPayload](MessageWithPayload.jsonBytes)
}
关于java - 快速解析具有较大可跳过区域的 JSON,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56872938/
我的算法- private static MyList skip$DeleteItem(MyList L , int M , int N){ MyList curr = L; MyLi
我正在 SWI-Prolog 下开发,但我的目标是 Erlog (https://github.com/rvirding/erlog)。我需要一种使用非标准 Prolog 语法的方法。 有没有办法
我正在尝试从应用程序下载一大堆文件。它的shell命令是“下载文件名”。 我有一个文本文件,其中包含必须下载的所有文件名。我要做的就是运行一个脚本/命令,以便在执行上述命令时 1.从文本文件中提取文件
我试图循环遍历所有用户的评论,但使用 if 语句查找特定值。问题是我的应用程序崩溃了,因为一些用户没有发表评论,因此我得到“无法读取‘收集’未定义的属性”。如何跳过 if 语句的未定义值?代码如下:
我们有按年份分区的索引,例如: items-2019 items-2020 考虑以下数据: POST items-2019/_doc { "@timestamp": "2019-01-01" }
我只是编写一个页面来按实体编号查看每个 ASCII 条目,我想知道是否有一种更简单/更干净的方法来跳过不需要的数字。 var x = new Ar
我希望能够普遍使用重复条目,但也能够跳过特定日期。例子: ** TODO swim practice SCHEDULED 但是,我提前知道 2013-12-25 不会有练习。但是,当我将项目标
如何跳过像这样的 for 循环的一次迭代: for (int i = 65; i <= 90; i++) { if (!(i == 73)) { uniq.add((char) i);
这个问题已经存在: Scanner issue when using nextLine after nextXXX [duplicate] 已关闭 9 年前。 ask=1; while(ask==1)
我在使用一个程序时遇到了一些麻烦,我应该允许用户在程序中输入任意数量的数字,直到他们不再想要为止。然后程序应该计算输入数字的平均值和最大值。我哪里做错了? import java.util.Scann
我有一个名为segments的 Sprite 数组,我想在每个循环中跳过segments的第一个元素。我目前正在这样做: var first = true; for each (var segment
我目前正在编写一个 for 循环来遍历包含 38 个元素的 2D。然而,其中一些元素为空,我希望 for 循环简单地跳过它们(因为在我正在解决的难题中,它们没有与它们相关的移动)。快速搜索表明,我可以
我想使用pre-commit处理我的 git 项目的 git hooks。但是,当我使用它时,git commit 命令不断跳过 unittest 执行: (smartexchange) trnboo
这个问题在这里已经有了答案: Does scanf() take '\n' as input leftover from previous scanf()? (1 个回答) 关闭 9 年前。 我正在
我正在迭代 csv 文件中的每一行,并仅选择/计算满足条件的行。但是,当连续出现错误时,它会停止循环。有没有办法告诉 python 跳过错误并移动到下一行?我使用了 try 函数但没有工作。我的代码是
感谢您提供的优秀示例,我试过了,它按我的预期工作。很高兴看到有人了解问题的本质。但是,我认为我应该用 Lift 标记问题,因为我正在使用 Lift 框架,这就是(仍然)发生这个问题的地方(尽管我仍然认
大家好,我正在编写一个算法来从 NodeTree 中删除具体分支(例如 DSF)。如果您选择 Node 的名称,算法将检查该 Node 是否是其他 Node 的父 Node ;如果是,它会获取该 No
附有代码和输出。 基本上它是第二次跳过我的输入。就像我启动代码一样,它让我输入一个选项,然后第二次跳过输入,直接转到开关的默认情况。 然后第三次它就会允许我输入。不明白为什么。 任何帮助将不胜感激。
我在 JavaScript 中有一个 for 循环,它会定期跳过间隔,但我无法确定原因。 console.log(parseInt($('input.num-to-add').val())); num
我正在 JasperSoft 中填写参数。在我的报告中我有参数:参数_1、参数_2、参数_3 int a; for (a = 0; a < headers.length; a++) {
我是一名优秀的程序员,十分优秀!