Scala新手使用Jackson库读取JSON文件遭遇UnrecognizedPropertyException错误求助
Fixing Jackson's UnrecognizedPropertyException in Scala
Hey there! Let's break down why you're hitting this error and how to fix it properly.
Why the Error Happens
That UnrecognizedPropertyException is telling you your JSON structure doesn't match the Inventory case class you defined. Here's the mismatch:
- Your JSON is a top-level object with three keys:
Rice,Pulses,Wheats— each maps to an array of items withnameandprice. - But your
Inventoryclass only hasnameandpricefields. Jackson is trying to shove the entire JSON (with thoseRice/Pulses/Wheatskeys) into anInventoryinstance, which has no place for those keys — hence the error.
How to Fix It
We need to align your Scala classes with the actual structure of your JSON. Here are two solid approaches:
Approach 1: Define Case Classes That Match the JSON Structure
Let's create two layers of case classes: one for individual items, and one for the top-level inventory structure.
// Case class for a single item (matches the objects inside each array) case class Item(name: String, price: Int) // Note: price is an Int, not String (your JSON uses numbers!) // Case class for the entire inventory (matches the top-level JSON object) case class InventoryData(Rice: List[Item], Pulses: List[Item], Wheats: List[Item]) object InventoryDataManagement { def main(args: Array[String]): Unit = { val mapper = JsonMapper.builder() .addModule(DefaultScalaModule) .build() val src = new File("src/main/json/inventary.json") // Map the JSON to our InventoryData class instead of Inventory val inventory = mapper.readValue(src, classOf[InventoryData]) // Example: Print all rice items println("Rice Inventory:") inventory.Rice.foreach(item => println(s"${item.name} - ₹${item.price}")) // Print pulses too! println("\nPulses Inventory:") inventory.Pulses.foreach(item => println(s"${item.name} - ₹${item.price}")) } }
Approach 2: Use a Map for Flexible Category Handling
If you might add more categories later (like Spices or Oils) and don't want to update your case class every time, map the JSON directly to a Map[String, List[Item]]:
case class Item(name: String, price: Int) object InventoryDataManagement { def main(args: Array[String]): Unit = { val mapper = JsonMapper.builder() .addModule(DefaultScalaModule) .build() val src = new File("src/main/json/inventary.json") // Map the JSON to a Map where keys are category names, values are item lists val inventoryMap = mapper.readValue(src, classOf[Map[String, List[Item]]]) // Loop through all categories and their items inventoryMap.foreach { case (category, items) => println(s"\n$category:") items.foreach(item => println(s" • ${item.name}: ₹${item.price}")) } } }
Quick Extra Tips
- Fix the Price Type: Your original
Inventoryclass hadpriceas aString, but your JSON uses numeric values. Changing it toInt(orDoubleif you have decimals) avoids unnecessary type conversions and errors. - Ignore Unknown Fields (Optional): If you ever have JSON with extra fields you don't care about, you can tell Jackson to ignore them to avoid similar errors:
val mapper = JsonMapper.builder() .addModule(DefaultScalaModule) .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) .build()
内容的提问来源于stack exchange,提问作者Piyush Jiwane




