我有一个有趣的问题。我想将一个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库,但如果您需要返回JsonObject
s并希望以更具功能性的样式进行返回,您可以执行:
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