From a2d48a5896335a567ddb21ed87fe38cd65d4764d Mon Sep 17 00:00:00 2001 From: Fabian Schuiki Date: Fri, 25 Mar 2022 19:53:43 +0100 Subject: Fix anno deserialization when class field is not first (#2501) Update `findTypeHints` to allow for the "class" field in JSON objects to appear anywhere in the object. This used to rely on the field being the very first in the object, which is easily violated when reading JSON data generated externally, since an object's order of fields is unspecified and can be arbitrarily scrambled. Fixes #2497.--- src/main/scala/firrtl/annotations/JsonProtocol.scala | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'src/main') diff --git a/src/main/scala/firrtl/annotations/JsonProtocol.scala b/src/main/scala/firrtl/annotations/JsonProtocol.scala index 6908a3a1..24ebc781 100644 --- a/src/main/scala/firrtl/annotations/JsonProtocol.scala +++ b/src/main/scala/firrtl/annotations/JsonProtocol.scala @@ -315,12 +315,13 @@ object JsonProtocol extends LazyLogging { // this used on the first invocation to check all annotations do so def findTypeHints(classInst: Seq[JValue], requireClassField: Boolean = false): Seq[String] = classInst .flatMap({ - case JObject(("class", JString(name)) :: fields) => name +: findTypeHints(fields.map(_._2)) - case obj: JObject if requireClassField => - throw new InvalidAnnotationJSONException(s"Expected field 'class' not found! $obj") - case JObject(fields) => findTypeHints(fields.map(_._2)) - case JArray(arr) => findTypeHints(arr) - case _ => Seq() + case JObject(fields) => + val hint = fields.collectFirst { case ("class", JString(name)) => name } + if (requireClassField && hint.isEmpty) + throw new InvalidAnnotationJSONException(s"Expected field 'class' not found! $fields") + hint ++: findTypeHints(fields.map(_._2)) + case JArray(arr) => findTypeHints(arr) + case _ => Seq() }) .distinct -- cgit v1.2.3