在Groovy中将XML转换为JSON

时间:2021-11-24 22:18:19

I wish to convert xml to JSON using groovy. I understand the specifics of conversion is dependent on my preferences, but could someone please recommend which libraries and methods I should be using and provide me with a little information on why/how to use them? I am using groovy as I have been told it is a very effective parser, so I am looking for libraries that will take advantage of this

我希望使用groovy将xml转换成JSON。我知道转换的具体细节取决于我的偏好,但是有人能给我推荐我应该使用的库和方法吗?我使用了groovy,因为我被告知它是一个非常有效的解析器,所以我正在寻找能够利用它的库。

Thanks!

谢谢!

4 个解决方案

#1


8  

You can do it all with basic Groovy:

你可以用基本的Groovy来完成:

// Given an XML string
def xml = '''<root>
            |    <node>Tim</node>
            |    <node>Tom</node>
            |</root>'''.stripMargin()

// Parse it
def parsed = new XmlParser().parseText( xml )

// Convert it to a Map containing a List of Maps
def jsonObject = [ root: parsed.node.collect {
  [ node: it.text() ]
} ]

// And dump it as Json
def json = new groovy.json.JsonBuilder( jsonObject )

// Check it's what we expected
assert json.toString() == '{"root":[{"node":"Tim"},{"node":"Tom"}]}'

HOWEVER, you really need to think about certain things...

然而,你真的需要考虑一些事情……

  • How are you going to represent Attributes?
  • 如何表示属性?
  • Will your XML contain <node>text<another>woo</another>text</node> style markup? If so, how are you going to handle that?
  • 您的XML是否包含 text woo text style markup?如果是的话,你打算怎么处理?
  • CDATA? Comments? etc?
  • CDATA吗?评论?等等?

It's not a smooth 1:1 mapping between the two... But for a given specific format of XML, it may be possible to come up with a given specific format of Json.

这两者之间并不是一个平滑的1:1映射…但是对于给定的特定XML格式,可能会得到特定的Json格式。

Update:

To get the names from the document (see comment), you can do:

要从文档中获取名称(请参阅注释),您可以:

def jsonObject = [ (parsed.name()): parsed.collect {
  [ (it.name()): it.text() ]
} ]

Update 2

You can add support for greater depth with:

您可以使用以下方法添加支持:

// Given an XML string
def xml = '''<root>
            |    <node>Tim</node>
            |    <node>Tom</node>
            |    <node>
            |      <anotherNode>another</anotherNode>
            |    </node>
            |</root>'''.stripMargin()

// Parse it
def parsed = new XmlParser().parseText( xml )

// Deal with each node:
def handle
handle = { node ->
  if( node instanceof String ) {
      node
  }
  else {
      [ (node.name()): node.collect( handle ) ]
  }
}
// Convert it to a Map containing a List of Maps
def jsonObject = [ (parsed.name()): parsed.collect { node ->
   [ (node.name()): node.collect( handle ) ]
} ]

// And dump it as Json
def json = new groovy.json.JsonBuilder( jsonObject )

// Check it's what we expected
assert json.toString() == '{"root":[{"node":["Tim"]},{"node":["Tom"]},{"node":[{"anotherNode":["another"]}]}]}'

Again, all the previous warnings still hold true (but should be heard a little louder at this point) ;-)

再一次,所有先前的警告仍然成立(但是现在应该被听到更大一点);

#2


5  

This would do the job: http://www.json.org/java/

这将完成以下工作:http://www.json.org/java/

At the time of writing this answer, the jar is available on: http://mvnrepository.com/artifact/org.json/json/20140107

在编写这个答案的时候,jar可以在:http://mvnrepository.com/artifact/org.json/json/20140107上找到。

The following shows the usage.

下面显示了用法。


Imports:

进口:

import org.json.JSONObject
import org.json.XML

Conversion:

转换:

static String convert(final String input) {
  int textIndent = 2
  JSONObject xmlJSONObj = XML.toJSONObject(input)
  xmlJSONObj.toString(textIndent)
}

Related Spock tests to show certain scenarios that we need to watch out for:

相关的Spock测试显示了我们需要注意的某些情况:

void "If tag and content are available, the content is put into a content attribute"() {
  given:
  String xml1 = '''
  <tag attr1="value">
    hello
  </tag>
  '''
  and:
  String xml2 = '''
  <tag attr1="value" content="hello"></tag>
  '''
  and:
  String xml3 = '''
  <tag attr1="value" content="hello" />
  '''
  and:
  String json = '''
  {"tag": {
      "content": "hello",
      "attr1": "value"
  }}
  '''

  expect:
  StringUtils.deleteWhitespace(convert(xml1)) == StringUtils.deleteWhitespace(json)
  StringUtils.deleteWhitespace(convert(xml2)) == StringUtils.deleteWhitespace(json)
  StringUtils.deleteWhitespace(convert(xml3)) == StringUtils.deleteWhitespace(json)
}

void "The content attribute would be merged with the content as an array"() {
  given:
  String xml = '''
  <tag content="same as putting into the content"
       attr1="value">
    hello
  </tag>
  '''
  and:
  String json = '''
  {"tag": {
      "content": [
          "same as putting into the content",
          "hello"
      ],
      "attr1": "value"
  }}
  '''

  expect:
  StringUtils.deleteWhitespace(convert(xml)) == StringUtils.deleteWhitespace(json)
}

void "If no additional attributes, the content attribute would be omitted, and it creates array in array instead"() {
  given:
  String xml = '''
  <tag content="same as putting into the content" >
    hello
  </tag>
  '''
  and:
  String notExpected = '''
  {"tag": {[
          "same as putting into the content",
          "hello"
          ]}
  }
  '''
  String json = '''
  {"tag": [[
          "same as putting into the content",
          "hello"
          ]]
  }
  '''

  expect:
  StringUtils.deleteWhitespace(convert(xml)) != StringUtils.deleteWhitespace(notExpected)
  StringUtils.deleteWhitespace(convert(xml)) == StringUtils.deleteWhitespace(json)
}

Hope this helps anyone who still need to resolve this problem.

希望这能帮助任何需要解决这个问题的人。

#3


1  

I'm a bit late to the party, but the following code will convert any XML into a consistent JSON format:

我来晚了一点,但是下面的代码将把任何XML转换成一致的JSON格式:

def toJsonBuilder(xml){
    def pojo = build(new XmlParser().parseText(xml))
    new groovy.json.JsonBuilder(pojo)
}
def build(node){
    if (node instanceof String){ 
        return // ignore strings...
    }
    def map = ['name': node.name()]
    if (!node.attributes().isEmpty()) {
        map.put('attributes', node.attributes().collectEntries{it})
    }
    if (!node.children().isEmpty() && !(node.children().get(0) instanceof String)) { 
        map.put('children', node.children().collect{build(it)}.findAll{it != null})
    } else if (node.text() != ''){
        map.put('value', node.text())
    }
    map
}
toJsonBuilder(xml1).toPrettyString()

Converts the XML...

将XML转换为…

<root>
    <node>Tim</node>
    <node>Tom</node>
</root>

Into...

成……

{
    "name": "root",
    "children": [
        {
            "name": "node",
            "value": "Tim"
        },
        {
            "name": "node",
            "value": "Tom"
        }
    ]
}

Feedback/improvements welcome!

反馈/改进欢迎!

#4


0  

I utilised staxon to get complex XML to JSON with staxon. This included elements with attributes.

我使用staxon将复杂的XML转换为JSON。这包括具有属性的元素。

The following has an example of converting xml to json.

下面是将xml转换为json的示例。

https://github.com/beckchr/staxon/wiki/Converting-XML-to-JSON

https://github.com/beckchr/staxon/wiki/Converting-XML-to-JSON

#1


8  

You can do it all with basic Groovy:

你可以用基本的Groovy来完成:

// Given an XML string
def xml = '''<root>
            |    <node>Tim</node>
            |    <node>Tom</node>
            |</root>'''.stripMargin()

// Parse it
def parsed = new XmlParser().parseText( xml )

// Convert it to a Map containing a List of Maps
def jsonObject = [ root: parsed.node.collect {
  [ node: it.text() ]
} ]

// And dump it as Json
def json = new groovy.json.JsonBuilder( jsonObject )

// Check it's what we expected
assert json.toString() == '{"root":[{"node":"Tim"},{"node":"Tom"}]}'

HOWEVER, you really need to think about certain things...

然而,你真的需要考虑一些事情……

  • How are you going to represent Attributes?
  • 如何表示属性?
  • Will your XML contain <node>text<another>woo</another>text</node> style markup? If so, how are you going to handle that?
  • 您的XML是否包含 text woo text style markup?如果是的话,你打算怎么处理?
  • CDATA? Comments? etc?
  • CDATA吗?评论?等等?

It's not a smooth 1:1 mapping between the two... But for a given specific format of XML, it may be possible to come up with a given specific format of Json.

这两者之间并不是一个平滑的1:1映射…但是对于给定的特定XML格式,可能会得到特定的Json格式。

Update:

To get the names from the document (see comment), you can do:

要从文档中获取名称(请参阅注释),您可以:

def jsonObject = [ (parsed.name()): parsed.collect {
  [ (it.name()): it.text() ]
} ]

Update 2

You can add support for greater depth with:

您可以使用以下方法添加支持:

// Given an XML string
def xml = '''<root>
            |    <node>Tim</node>
            |    <node>Tom</node>
            |    <node>
            |      <anotherNode>another</anotherNode>
            |    </node>
            |</root>'''.stripMargin()

// Parse it
def parsed = new XmlParser().parseText( xml )

// Deal with each node:
def handle
handle = { node ->
  if( node instanceof String ) {
      node
  }
  else {
      [ (node.name()): node.collect( handle ) ]
  }
}
// Convert it to a Map containing a List of Maps
def jsonObject = [ (parsed.name()): parsed.collect { node ->
   [ (node.name()): node.collect( handle ) ]
} ]

// And dump it as Json
def json = new groovy.json.JsonBuilder( jsonObject )

// Check it's what we expected
assert json.toString() == '{"root":[{"node":["Tim"]},{"node":["Tom"]},{"node":[{"anotherNode":["another"]}]}]}'

Again, all the previous warnings still hold true (but should be heard a little louder at this point) ;-)

再一次,所有先前的警告仍然成立(但是现在应该被听到更大一点);

#2


5  

This would do the job: http://www.json.org/java/

这将完成以下工作:http://www.json.org/java/

At the time of writing this answer, the jar is available on: http://mvnrepository.com/artifact/org.json/json/20140107

在编写这个答案的时候,jar可以在:http://mvnrepository.com/artifact/org.json/json/20140107上找到。

The following shows the usage.

下面显示了用法。


Imports:

进口:

import org.json.JSONObject
import org.json.XML

Conversion:

转换:

static String convert(final String input) {
  int textIndent = 2
  JSONObject xmlJSONObj = XML.toJSONObject(input)
  xmlJSONObj.toString(textIndent)
}

Related Spock tests to show certain scenarios that we need to watch out for:

相关的Spock测试显示了我们需要注意的某些情况:

void "If tag and content are available, the content is put into a content attribute"() {
  given:
  String xml1 = '''
  <tag attr1="value">
    hello
  </tag>
  '''
  and:
  String xml2 = '''
  <tag attr1="value" content="hello"></tag>
  '''
  and:
  String xml3 = '''
  <tag attr1="value" content="hello" />
  '''
  and:
  String json = '''
  {"tag": {
      "content": "hello",
      "attr1": "value"
  }}
  '''

  expect:
  StringUtils.deleteWhitespace(convert(xml1)) == StringUtils.deleteWhitespace(json)
  StringUtils.deleteWhitespace(convert(xml2)) == StringUtils.deleteWhitespace(json)
  StringUtils.deleteWhitespace(convert(xml3)) == StringUtils.deleteWhitespace(json)
}

void "The content attribute would be merged with the content as an array"() {
  given:
  String xml = '''
  <tag content="same as putting into the content"
       attr1="value">
    hello
  </tag>
  '''
  and:
  String json = '''
  {"tag": {
      "content": [
          "same as putting into the content",
          "hello"
      ],
      "attr1": "value"
  }}
  '''

  expect:
  StringUtils.deleteWhitespace(convert(xml)) == StringUtils.deleteWhitespace(json)
}

void "If no additional attributes, the content attribute would be omitted, and it creates array in array instead"() {
  given:
  String xml = '''
  <tag content="same as putting into the content" >
    hello
  </tag>
  '''
  and:
  String notExpected = '''
  {"tag": {[
          "same as putting into the content",
          "hello"
          ]}
  }
  '''
  String json = '''
  {"tag": [[
          "same as putting into the content",
          "hello"
          ]]
  }
  '''

  expect:
  StringUtils.deleteWhitespace(convert(xml)) != StringUtils.deleteWhitespace(notExpected)
  StringUtils.deleteWhitespace(convert(xml)) == StringUtils.deleteWhitespace(json)
}

Hope this helps anyone who still need to resolve this problem.

希望这能帮助任何需要解决这个问题的人。

#3


1  

I'm a bit late to the party, but the following code will convert any XML into a consistent JSON format:

我来晚了一点,但是下面的代码将把任何XML转换成一致的JSON格式:

def toJsonBuilder(xml){
    def pojo = build(new XmlParser().parseText(xml))
    new groovy.json.JsonBuilder(pojo)
}
def build(node){
    if (node instanceof String){ 
        return // ignore strings...
    }
    def map = ['name': node.name()]
    if (!node.attributes().isEmpty()) {
        map.put('attributes', node.attributes().collectEntries{it})
    }
    if (!node.children().isEmpty() && !(node.children().get(0) instanceof String)) { 
        map.put('children', node.children().collect{build(it)}.findAll{it != null})
    } else if (node.text() != ''){
        map.put('value', node.text())
    }
    map
}
toJsonBuilder(xml1).toPrettyString()

Converts the XML...

将XML转换为…

<root>
    <node>Tim</node>
    <node>Tom</node>
</root>

Into...

成……

{
    "name": "root",
    "children": [
        {
            "name": "node",
            "value": "Tim"
        },
        {
            "name": "node",
            "value": "Tom"
        }
    ]
}

Feedback/improvements welcome!

反馈/改进欢迎!

#4


0  

I utilised staxon to get complex XML to JSON with staxon. This included elements with attributes.

我使用staxon将复杂的XML转换为JSON。这包括具有属性的元素。

The following has an example of converting xml to json.

下面是将xml转换为json的示例。

https://github.com/beckchr/staxon/wiki/Converting-XML-to-JSON

https://github.com/beckchr/staxon/wiki/Converting-XML-to-JSON