Scala Play JSON:遍历JsArray/JsObject统计值为Null的键出现次数
Hey there! Let's figure out how to count those null-valued keys in your JSON using Play JSON—no external libraries needed. I’ve run into this exact confusion before, so let’s break it down step by step.
Why You’re Seeing "map doesn’t exist" Errors
First up: Play JSON’s JsObject and JsArray aren’t directly traversable collections. You can’t call map on them directly because they’re wrapper classes—you need to access their internal sequence properties first:
- For
JsObject, use thefieldsproperty (it returns aSeq[(String, JsValue)]of all key-value pairs) - For
JsArray, use thevalueproperty (it returns aSeq[JsValue]of all elements)
Recursive Solution for Nested JSON
Since JSON is often nested (objects inside objects, arrays of objects), we’ll write a recursive function to traverse every level and count all keys with JsNull values. Here’s the code:
import play.api.libs.json._ def countNullKeys(json: JsValue): Int = json match { // Handle objects: check each key's value, count nulls, then recurse into the value case JsObject(fields) => fields.foldLeft(0) { (totalCount, (key, value)) => // Add 1 if this key's value is null val currentNull = if (value == JsNull) 1 else 0 // Add current null count plus any nulls in nested structures totalCount + currentNull + countNullKeys(value) } // Handle arrays: recurse into each element and sum the counts case JsArray(elements) => elements.foldLeft(0)(_ + countNullKeys(_)) // All other JSON types (strings, numbers, nulls not tied to a key) contribute 0 case _ => 0 }
Test It Out
Let’s use a sample university domain JSON to see it in action:
// Sample university JSON with nested nulls val universityJson = Json.parse(""" { "name": "Stanford University", "primary_domain": null, "secondary_domains": [ {"domain": "cs.stanford.edu", "contact": null}, {"domain": "med.stanford.edu", "contact": "med-admin@stanford.edu"} ], "admin": { "name": null, "email": "admin@stanford.edu" } } """) // Should return 3: primary_domain, contact (CS dept), name (admin) println(countNullKeys(universityJson))
If You Only Need Top-Level Nulls
If you don’t care about nested nulls and just want to count top-level keys with null values, simplify the function:
def countTopLevelNullKeys(json: JsValue): Int = json match { case JsObject(fields) => fields.count(_._2 == JsNull) case _ => 0 }
Fixing Your Pattern Matching Issues
Chances are your earlier pattern matching failed because you didn’t extract the internal collections. Instead of writing case JsObject =>, use case JsObject(fields) to get access to the key-value pairs. Same for arrays: case JsArray(elements) lets you iterate over the array’s contents.
内容的提问来源于stack exchange,提问作者royki

