0

I have an interesting problem. I want to process an XML file into individual JSON objects (JSONObject). But in a functional way.

I have a source XMLfile that contains Property Groups. Each group containing properties (see below).

The only way to tell if a group belongs to different products is by the id attribute.

<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>

My code for processing this XML file looks like this:

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
}

Although this works and does what it is supposed to do, it is not 'functional style'. How do I change this from the imperative mind-set to a functional style?

Adam Davies
  • 2,742
  • 4
  • 33
  • 52

1 Answers1

1

The JavaEE JSON API is not the most functional JSON library, but if you need to return JsonObjects and want to do it in a more functional style, you could do:

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
Peter Neyens
  • 9,770
  • 27
  • 33
  • OK interesting, what would be a better option than JSONObject? – Adam Davies Jun 23 '15 at 09:57
  • There are a lot of good [Scala Json libraries](http://stackoverflow.com/a/14442630/5020846). – Peter Neyens Jun 23 '15 at 10:06
  • Thanks Peter. As you can probably tell form my code snippet I come from a Java background. Can you recommend any reading to get into the Scala and functional mind-set. Particularly all those idiomatics of functional such as the _._1 stuff. Thanks again. – Adam Davies Jun 23 '15 at 13:04
  • @AdamDavies Yes, it takes some time getting used to the more functional style of Scala. You could start with [Programming in Scala (ed 1)](http://www.artima.com/pins1ed/) and there are two courses on Coursera about Scala. – Peter Neyens Jun 23 '15 at 13:10