【问题标题】:Scala: Parsing JSON using the org.fastxml.jackson libraryScala:使用 org.fasterxml.jackson 库解析 JSON
【发布时间】:2015-05-18 04:48:55
【问题描述】:

我编写了以下程序以流方式解析 JSON 结构。

但是,这看起来非常必要。这是我最近尝试编写更惯用的 Scala 代码,但我还没有。

我正在解析以下 JSON,使用 JSON sn-p 之后的 Scala 代码。我的目标是通过使用更惯用的 scala 结构来缩短代码。 提前致谢。

{
    "type": "ImportantIncidentInfo",
    "incidentTimestamp": "2014-05-15T10:09:27.989-05:00",
    "numOfMatches": 4,
    "myReport": {
        "docReports": {
            "part1/.": {
                "path": [
                    "unknown"
                ],
                "myAnalysis": {
                    "matches": [
                        {
                            "id": {
                                "major": 1,
                                "minor": 0
                            },
                            "name": "US SSN",
                            "position": 13,
                            "string": " 636-12-4567 "
                        },
                        {
                            "id": {
                                "major": 3,
                                "minor": 0
                            },
                            "name": "MasterCard Credit Card Number",
                            "position": 35,
                            "string": " 5424-1813-6924-3685 "
                        }
                    ]
                },
                "cleanedUpData": [
                    {
                        "startPosition": 0,
                        "endPosition": 65,
                        "frameContent": ""
                    }
                ],
                "minedMetadata": {
                    "Content-Encoding": "ISO-8859-1",
                    "Content-Type": "text/html; charset=iso-8859-1"
                },
                "deducedMetadata": {
                    "Content-Type": "text/html; iso-8859-1"
                }
            },
            "part2/.": {
                "path": [
                    "unknown"
                ],
                "myAnalysis": {
                    "matches": [
                        {
                            "id": {
                                "major": 1,
                                "minor": 0
                            },
                            "name": "SSN",
                            "position": 3,
                            "string": " 636-12-4567\r"
                        },
                        {
                            "id": {
                                "major": 3,
                                "minor": 0
                            },
                            "name": "MasterCard Credit Card Number",
                            "position": 18,
                            "string": "\n5424-1813-6924-3685\r"
                        }
                    ]
                },
                "cleanedUpData": [
                    {
                        "startPosition": 0,
                        "endPosition": 44,
                        "frameContent": ""
                    }
                ],
                "minedMetadata": {
                    "Content-Encoding": "windows-1252",
                    "Content-Type": "text/plain; charset=windows-1252"
                },
                "deducedMetadata": {
                    "Content-Type": "text/plain; iso-8859-1"
                }
            }
        }
    },
    "whatSetItOffEntry": {
        "action": "Log",
        "component": {
            "type": "aComponent",
            "components": [
                {
                    "type": "PatternComponent",
                    "patterns": [
                        1
                    ],
                    "not": false
                }
            ],
            "not": false
        },
        "ticketInfo": {
            "createIncident": true,
            "tags": [],
            "seeRestrictedIds": [
                {
                    "type": "userGroup",
                    "name": "SiteMasters",
                    "description": "Group for SiteMasters",
                    "masters": [
                        "04fb02a2bc0fba"
                    ],
                    "members": [],
                    "id": "04fade"
                }
            ]
        },
        "letmeknowInfo": {
            "createNotification": true,
            "contactNames": [
                "someguy@gmail.com"
            ]
        }
    },
    "seeRestrictedIds": [
        "04fade66c0"
    ],
    "status": "New",
    "timeStamps": [
        "2015-05-15T10:09:27.989-05:00"
    ],
    "count": 1
}

打包我的包裹 导入 java.io.BufferedReader 导入 java.io.FileReader 导入 java.io.IOException 导入 java.io.InputStream 导入 java.util._ 导入 com.fasterxml.jackson.core._ 导入 com.fasterxml.jackson.databind._ 导入 java.util.Properties 导入 JacksonStreaming._

object JacksonStreaming {

  def main(args: Array[String]) {
    println("Entered Main")
    try {
      new JacksonStreaming().getNames
    } catch {
      case e: Exception => e.printStackTrace()
    }
  }
}

class JacksonStreaming {

  var jsonMapper: ObjectMapper = new ObjectMapper()

  var jsonFactory: JsonFactory = new JsonFactory()

  var prop: Properties = new Properties()

  var filePath: String = ""

  val path = Array("myReport", "docReports", "part1/.", "myAnalysis", "matches", "name")

  def getNames() {
    println("Entered getNames")
    var rootNode: JsonNode = null
    try {
      val fileReader = new BufferedReader(new FileReader("C:/jsonFormattedModified.json"))
      println("fileReader is: " + fileReader)
      rootNode = jsonMapper.readTree(fileReader)
      println("Return value of jsonMapper.readTree is: " + rootNode)
      findByPath(rootNode)
      val jsonParser = jsonFactory.createParser(new FileReader("C:/jsonFormattedModified.json"))
      println("JsonParser is: " + jsonParser)
      var pathIndex = 0
      val names = new ArrayList[String]()
      var breakOnClose = false
      while (jsonParser.nextToken() != null) {
        val fieldName = jsonParser.getCurrentName
        if (fieldName == null) {
          //continue
        }
        if (breakOnClose && fieldName == path(path.length - 2)) {
          println("Stopping search at end of node " + fieldName)
          //break
        }
        if (jsonParser.getCurrentToken != JsonToken.FIELD_NAME) {
          //continue
        }
        if (pathIndex >= path.length - 1) {
          if (fieldName == path(path.length - 1)) {
            try {
              jsonParser.nextToken()
            } catch {
              case e: IOException => e.printStackTrace()
            }
            var name: String = null
            name = jsonParser.getValueAsString
            if (name == null) {
              throw new RuntimeException("No value exists for field " + fieldName)
            }
            names.add(name)
            println("Found " + fieldName + " value: " + name)
          }
        } else if (fieldName == path(pathIndex)) {
          println("Found node " + path(pathIndex))
          pathIndex += 1
          if (pathIndex >= path.length - 1) {
            println("Looking for names ...")
            breakOnClose = true
            try {
              jsonParser.nextFieldName()
            } catch {
              case e: IOException => e.printStackTrace()
            }
          }
        }
      }
    } catch {
      case e: IOException => e.printStackTrace()
    }
  }

  def findByPath(jn: JsonNode) {
    println("Entered findByPath")
    var matchesNamesNode = jn
    for (i <- 0 until path.length - 1) {
      matchesNamesNode = matchesNamesNode.path(path(i))
    }
    if (matchesNamesNode.isMissingNode) {
      throw new RuntimeException("No node with names found.")
    }
    println("Tree names: " + matchesNamesNode.findValuesAsText("name"))
  }
}

【问题讨论】:

  • 代码可能太长且不清楚,以至于有人为您重写它,这就是您要问的。我建议你自己再试一次。作为指导,请尝试在没有var 变量、没有for 循环、没有try/catch 块的情况下执行此操作,并将if 语句的数量减少到最低限度。
  • 没有人需要为我重写它。您的建议很好,我会尝试自己重写。

标签: json scala


【解决方案1】:

我认为 Scala 是面向表达式、面向对象和函数式编程语言,当然你可以写成命令式的,但是对于 JSON,我建议你去使用面向对象,你可以找到例子,它是 github repository

https://github.com/FasterXML/jackson-module-scala/

例如,我建议您编写一个 Scala,为所有 Json 编写类,然后为诸如 MyReport 或 whatSetItOffEntry 之类的子对象,在 github 存储库中是存储库中此类解决方案的示例:

package com.fasterxml.jackson.module.scala

import com.fasterxml.jackson.annotation.{JsonUnwrapped, JsonProperty, JsonIgnore}
import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner
import org.scalatest.matchers.ShouldMatchers
import org.scalatest.FlatSpec
import com.fasterxml.jackson.databind.ObjectMapper


case class Address(address1: Option[String], city: Option[String], state: Option[String])

class NonCreatorPerson
{
  var name: String = _
  @JsonUnwrapped var location: Address = _
  var alias: Option[String] = _
}

case class Person(name: String, @JsonIgnore location: Address, alias: Option[String])
{
  private def this() = this("", Address(None, None, None), None)

  def address1 = location.address1
  private def address1_=(value: Option[String]) {
    setAddressField("address1", value)
  }

  def city = location.city
  private def city_=(value: Option[String]) {
    setAddressField("city", value)
  }

  def state = location.state
  private def state_= (value: Option[String]) {
    setAddressField("state", value)
  }

  private def setAddressField(name: String, value: Option[String])
  {
    val f = location.getClass.getDeclaredField(name)
    f.setAccessible(true)
    f.set(location, value)
  }
}

@RunWith(classOf[JUnitRunner])
class UnwrappedTest extends BaseSpec {

  "mapper" should "handle ignored fields correctly" in {
    val mapper = new ObjectMapper()
    mapper.registerModule(DefaultScalaModule)

    val p = Person("Snoopy", Address(Some("123 Main St"), Some("Anytown"), Some("WA")), Some("Joe Cool"))
    val json = mapper.writeValueAsString(p)

    // There's some instability in the ordering of keys. Not sure what that's about, but rather than
    // have buggy tests, I'm accepting it for now.
    //    json should (
    //      be === """{"name":"Snoopy","alias":"Joe Cool","city":"Anytown","address1":"123 Main St","state":"WA"}""" or
    //      be === """{"name":"Snoopy","alias":"Joe Cool","state":"WA","address1":"123 Main St","city":"Anytown"}"""
    //    )

    val p2 = mapper.readValue(json, classOf[Person])

    p2 shouldEqual p
  }

  it should "handle JsonUnwrapped for non-creators" in {
    val mapper = new ObjectMapper()
    mapper.registerModule(DefaultScalaModule)

    val p = new NonCreatorPerson
    p.name = "Snoopy"
    p.location = Address(Some("123 Main St"), Some("Anytown"), Some("WA"))
    p.alias = Some("Joe Cool")

    val json = mapper.writeValueAsString(p)
    val p2 = mapper.readValue(json, classOf[NonCreatorPerson])

    p2.name shouldBe p.name
    p2.location shouldBe p.location
    p2.alias shouldBe p.alias
  }
}

【讨论】:

  • 好的方向。我也在考虑案例类,你也给了我这个方向
  • 希望对您有所帮助:-)
  • 我刚才可以看到你的答案:)。对我来说看起来很不错。我要把它拿出来在我的系统上旋转一下。我可以告诉你进展如何吗?感谢您的努力
  • 当然,你可以我通常在java中使用jackson,所以最好知道它在scala中是如何工作的
  • 今晚我会检查你的代码,因为到目前为止我还没有机会这样做/谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-04-06
  • 1970-01-01
  • 2018-10-06
  • 2020-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多