抓到:java.lang.StackOverflowError JsonBuilder闭包

时间:2014-10-30 23:08:24

标签: groovy closures jsonbuilder

我一直在尝试读取xml文件并使用groovy的JsonBuilder将其转换为json。问题是当我用

打印时
def builder = new JsonBuilder(jsonObject)
println builder.toPrettyString()

我抓到了:java.lang.StackOverflowError

这是整个堆栈跟踪

Exception in thread "main" java.lang.StackOverflowError
    at groovy.json.JsonOutput.writeObject(JsonOutput.java:259)
    at groovy.json.JsonOutput.writeIterator(JsonOutput.java:442)
    at groovy.json.JsonOutput.writeObject(JsonOutput.java:272)
    at groovy.json.JsonOutput.writeIterator(JsonOutput.java:442)
    at groovy.json.JsonOutput.writeObject(JsonOutput.java:272)
    at groovy.json.JsonOutput.writeIterator(JsonOutput.java:442)
    at groovy.json.JsonOutput.writeObject(JsonOutput.java:272)
    at groovy.json.JsonOutput.writeIterator(JsonOutput.java:442)
    at groovy.json.JsonOutput.writeObject(JsonOutput.java:272)
    at groovy.json.JsonOutput.writeIterator(JsonOutput.java:442)
    at groovy.json.JsonOutput.writeObject(JsonOutput.java:272)
    at groovy.json.JsonOutput.writeIterator(JsonOutput.java:442)
    at groovy.json.JsonOutput.writeObject(JsonOutput.java:272)
    at groovy.json.JsonOutput.writeIterator(JsonOutput.java:442)

这里的代码。

package firstgroovyproject

import groovy.json.JsonBuilder

class XmlToJsonII {
    static void main(def args){

        def carRecords = '''

<records>
    <car name='HSV Maloo' make='Holden' year='2006'>
        <countries>
            <country>
                Austria
            </country>
            <country>
                Spain
            </country>
        </countries>
        <record type='speed'>Production Pickup Truck with speed of 271kph
        </record>
    </car>
    <car name='P50' make='Peel' year='1962'>
        <countries>
            <country>
                Monaco
            </country>
        </countries>
        <record type='size'>Smallest Street-Legal Car at 99cm wide and 59 kg
            in weight</record>
    </car>
    <car name='Royale' make='Bugatti' year='1931'>
        <record type='price'>Most Valuable Car at $15 million</record>
        <countries>
            <country>
                Italia
            </country>
        </countries>
    </car>
<car name='Seat' make='Ibiza' year='1985'>
        <record type='price'>barato</record>
        <countries>
            <country>
                Spain
            </country>
        </countries>
    </car>
</records>
  '''


        def xmlRecords = new XmlSlurper().parseText(carRecords)

        def jsonObject = [:]
        jsonObject.records = []
        def records = jsonObject.records



        xmlRecords.car.each {xmlCar ->  
            records.add([
                countries:
                xmlCar.countries.children().each{ country ->
                        println   "country : ${country.text()}"
                        [country:   country.text()]
                },

                ])
        }

        def builder = new JsonBuilder(jsonObject)

        println builder.toPrettyString()
        //println builder.toString()
    }
}

1 个答案:

答案 0 :(得分:4)

tl; dr:您的第二个(内部)each应该是collect

真正的答案: each的返回值是调用它的原始Iterable。在这种情况下,它将是由表达式xmlCar.countries.children()定义的XML对象集合。由于该集合中的对象包含对其父对象的引用,因此JSON构建会导致无限回归,从而导致堆栈溢出。

首次(外部)使用each时不会发生这种情况,因为您没有使用返回值。相反,您要添加到预先存在的列表(records)。

通过将第二个(内部)each更改为collect,您仍在迭代countries个元素的子元素。但是,您没有返回原始XML子项(each的结果),而是编译并返回[country:"country_string_from_xml"]形式的映射列表,这似乎是所需的行为。

令人困惑eachcollect是Groovy中常见的新手错误......这只会让上周发生在我身上的事情变得更加严重。 : - )