Scala-以函数风格处理XML到JSON对象



我有一个有趣的问题。我想将一个XML文件处理成单独的JSON对象(JSONObject)。但以一种功能性的方式。

我有一个包含属性组的源XML文件。每组包含属性(请参见下文)。

判断一个组是否属于不同产品的唯一方法是通过id属性。

<data>
  <products>
    <property_group classification="product_properties" id="1234">
      <property name="Name">Product1</property>
      <property name="Brand">Brand1</property>
      ...
    </property_group>
    <property_group classification="size_properties" id="1234">
      <property name="width">200cm</property>
      <property name="height">100cm</property>
      ...
    </property_group>
    ...
    <property_group classification="product_properties" id="5678">
      <property name="Name">Product2</property>
      <property name="Brand">Brand2</property>
      ...
    </property_group>
    <property_group classification="weight_properties" id="5678">
      <property name="kg">20</property>
      <property name="lbs">44</property>
      ...
    </property_group>
    ...
  </products>  
 </data>

我处理这个XML文件的代码如下:

def createProducts(propertyGroups: NodeSeq): MutableList[JSONObject] = {
  val products = new MutableList[JSONObject]
  var productJSON = new JSONObject()
  var currentProductID = "";
  propertyGroups.foreach { propertyGroup => {
    // Get data from the current property_group
    val productID = getProductID(propertyGroup)
    val propertiesClassification = getClassification(propertyGroup)
    val properties = getProductAttributes(propertyGroup \ "property")
    // Does this group relates to a new product?
    if(currentProductID != productID){
      // Starting a new Product
      productJSON = new JSONObject()
      products += productJSON
      productJSON.put("product", productID)
      currentProductID = productID
    }
    // Add the properties to the product
    val propertiesJSON = new JSONObject()
    propertiesJSON.put(propertiesClassification, properties)
    productJSON.put(propertiesClassification, properties)
  } }
  return products
}

尽管这是有效的,并且做了它应该做的事情,但它不是"功能风格"。我该如何将其从命令式思维转变为功能式风格?

JavaEE JSON API不是功能性最强的JSON库,但如果您需要返回JsonObjects并希望以更具功能性的样式进行返回,您可以执行:

def createProducts(propertyGroups: NodeSeq): List[JSONObject] = 
  propertyGroups
    // map to a (id, classification, properties) tuple
    .map { propertyGroup => 
      val productID = getProductID(propertyGroup)
      val propertiesClassification = getClassification(propertyGroup)
      val properties = getProductAttributes(propertyGroup \ "property")
      (productId, propertiesClassification, properties)
    }
    // group by product ID
    .groupBy(_._1)
    // turn grouped properties into json product
    .map { case (id, tuples) =>
      val product = new JSONObject()
      product.put("product", productID)
      // fold over all the tuples and add properties to the product json
      tuples.foldLeft(product) { case (accProd, (_, classif, properties)) =>
        // not exactly sure want you want to do with your propertiesJSON
        val propertiesJSON = new JSONObject()
        propertiesJSON.put(classif, properties)
        accProd.put(classif, properties)
        accProd
      }
    }.toList

最新更新