Groovy12_Jsonxmlswing与生成器
Posted 李樟清
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Groovy12_Jsonxmlswing与生成器相关的知识,希望对你有一定的参考价值。
1. Json 生成器 : JsonBuilder
import groovy.json.JsonBuilder
import groovy.json.JsonOutput
import groovy.json.JsonSlurper
""""""
// json 生成器
def builder = new JsonBuilder()
builder.json
first 'zeking'
last 'haha'
println builder // "json":"first":"zeking","last":"haha"
builder
first 'zeking'
last 'haha'
println builder // "first":"zeking","last":"haha"
class Person
def first
def last
def p = new Person(first: 'zekign',last:'haha')
// 转换对象为json数据
def b = new JsonBuilder(p)
println b.toString() // "first":"zekign","last":"haha"
println JsonOutput.toJson(p) // "first":"zekign","last":"haha"
// 格式化json数据
println JsonOutput.prettyPrint(JsonOutput.toJson(p))
//
// "first": "zekign",
// "last": "haha"
//
// 反序列化
def slurper = new JsonSlurper()
Person person = slurper.parseText(JsonOutput.toJson(p))
println person.first // zekign
println person.last // haha
2.xml 生成器 : MarkupBuilder
2.1 创建xml
xml_create.groovy
import groovy.xml.MarkupBuilder
import groovy.xml.StreamingMarkupBuilder
// xml 生成
"""<html><head m="a">hello</head></html>"""
//new File("baidu.html").write("https://www.baidu.com/".toURL().text)
def sw = new FileWriter(new File("normal.xml"))
def builder = new MarkupBuilder(sw)
builder.html
mkp.comment("测试") // 注释
head("hello",m:"a")
title("ZekingLee")
body
//<html><!-- 测试 -->
// <head m='a'>hello
// <title>ZekingLee</title>
// </head>
// <body />
//</html>
def sb = new StreamingMarkupBuilder()
sb.encoding = 'UTF-8'
def closure =
// 生成xml文件的版本和标识的方法
mkp.xmlDeclaration()
html
head(id:1)
def sw2 = sb.bind(closure)
println sw2.toString()
// <?xml version='1.0' encoding='UTF-8'?>
// <html><head id='1'></head></html>
2.2 解析xml
androidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.administrator.androidprotobuf">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<meta-data android:name="hello" android:value="1"/>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
xml_parse.groovy
import groovy.xml.Namespace
// parser 是个Node 就是 manifest节点
def parser = new XmlParser().parse(new File("AndroidManifest.xml"))
// 1.需求:拿到activity节点的name属性
// name属性有一个 android: 的命名空间
//命名空间
def ns = new Namespace('http://schemas.android.com/apk/res/android','android')
Node node = parser.application[0].activity[0]
println node.attributes()[ns.name] // .MainActivity
// 2.移除meta-data节点,添加节点
// 获得application节点
Node node2 = parser.application[0]
//NodeList
Node meta = node2.'meta-data'[0]
node2.remove(meta)
node2.appendNode('meta-data',[(ns.name):'a',(ns.value):'b',(ns.hh):'hh'])
new XmlNodePrinter(new PrintWriter(new File("replace.xml"))).print(parser)
//<manifest package="com.example.administrator.androidprotobuf">
// <application android:allowBackup="true" xmlns:android="http://schemas.android.com/apk/res/android" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme">
// <activity android:name=".MainActivity">
// <intent-filter>
// <action android:name="android.intent.action.MAIN"/>
// <category android:name="android.intent.category.LAUNCHER"/>
// </intent-filter>
// </activity>
// <meta-data android:name="a" android:value="b" android:hh="hh"/>
// </application>
//</manifest>
//</manifest>
3. swing生成器 :SwingBuilder
import groovy.swing.SwingBuilder
import javax.swing.JButton
import javax.swing.JFrame
import javax.swing.JLabel
import javax.swing.WindowConstants
import java.awt.FlowLayout
// 使用groovy 写
def builder = new SwingBuilder()
def swing = builder.frame(title: '测试',size: [100,100],
layout: new FlowLayout(),defaultCloseOperation: WindowConstants.EXIT_ON_CLOSE)
label(text:'文本')
button(text:'按钮',actionPerformed:
)
swing.setVisible(true)
// 使用java代码写 ,对比一下,groovy简单很多
//def frame = new JFrame()
//frame.setTitle('测试')
//frame.setSize(100,100)
//frame.setLayout(new FlowLayout())
//frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE)
//new JLabel()
//new JButton().addActionListener
//
//
4. 模仿xm生成器 的 BuilderSupport自定义html生成器
MyBuildSupport.groovy
package builder
// 模仿xm生成器 的 MarkupBuilder 自定义生成器
class MyBuildSupport extends BuilderSupport
class Node
String name
String value
Map attr
def children // 将Node这个节点的所有子节点都保存到这个集合里面
Node(String name, String value, Map attr)
this.name = name
this.value = value
this.attr = attr
children = []
//<xml key='value'/>
//<xml>xxx</xml>
def build(Writer writer)
// 生成xml
writer.write("<$name")
if (attr)
attr.each
key,value->
writer.write(" $key='$value")
if (value || children)
writer.write(">")
if (value)
writer.write(value)
children.each
it.build(writer)
writer.write("</$name>")
else
writer.write("/>")
def nodes
Writer writer
MyBuildSupport(Writer writer)
nodes = [:]
this.writer = writer
/**
* 节点与节点的关系
* @param parent 父节点
* @param child 子节点
*/
@Override
protected void setParent(Object parent, Object child)
println "seParent $parent $child" // 这样是没有任何回调的
// 如何有回调,createNode 的 返回值会作为seParent的 参数 传递过来
/**
* 完成节点调用
* 通过这个方法可以知道
* 节点之间的关系 也可以知道 节点的完成情况
* @param parent
* @param node
*/
@Override
protected void nodeCompleted(Object parent, Object node)
super.nodeCompleted(parent, node)
println "nodeCompleted $parent $node"
def currentNode = nodes[node]
if (parent)
nodes[parent].children << currentNode
else
// 构建需要的格式
currentNode.build(writer)
@Override
protected Object createNode(Object name)
return createNode(name,null,null)
@Override
protected Object createNode(Object name, Object value)
return createNode(name,null,value)
@Override
protected Object createNode(Object name, Map attributes)
return createNode(name,attributes,null)
@Override
protected Object createNode(Object name, Map attributes, Object value)
println("create Node:$name $value $attributes")
nodes.put(name,new Node(name,value,attributes))
return name
MyBuilderTest.groovy
package builder
StringWriter sw = new StringWriter()
def builder = new MyBuildSupport(sw)
builder.html
head("zeking",key:'value')
title("Test")
body
x
y
z
println(sw)
//create Node:html null null
//create Node:head zeking [key:value]
//seParent html head
//create Node:title Test null
//seParent head title
//nodeCompleted head title
//nodeCompleted html head
//create Node:body null null
//seParent html body
//nodeCompleted html body
//create Node:x null null
//seParent html x
//create Node:y null null
//seParent x y
//create Node:z null null
//seParent y z
//nodeCompleted y z
//nodeCompleted x y
//nodeCompleted html x
//nodeCompleted null html
//<html><head key='value>zeking<title>Test</title></head><body/><x><y><z/></y></x></html>
5. 模仿swing生成器 的 FactoryBuilderSupport自定义html生成器
MyFactoryBuilderSupport.groovy
package builder
// 模仿swing生成器
// 工厂 buildsupport工厂
class Node
String name
String value
Map attr
def children // 将Node这个节点的所有子节点都保存到这个集合里面
Node(String name, String value, Map attr)
this.name = name
this.value = value
this.attr = attr
children = []
//<xml key='value'/>
//<xml>xxx</xml>
def build(Writer writer)
// 生成xml
writer.write("<$name")
if (attr)
attr.each
key,value->
writer.write(" $key='$value")
if (value || children)
writer.write(">")
if (value)
writer.write(value)
children.each
it.build(writer)
writer.write("</$name>")
else
writer.write("/>")
class MyFactoryBuilderSupport extends FactoryBuilderSupport
def nodeFactory = new NodeFactory()
// 注册html的工厂
registerFactory('html',new NodeFactory())
registerFactory('head',new NodeFactory())
class NodeFactory extends AbstractFactory
def name
/**
* 返回的参数就是我们调用html方法的结果
* @param builder
* @param name
* @param value
* @param attributes
* @return
* @throws InstantiationException
* @throws IllegalAccessException
*/
@Override
Object newInstance(FactoryBuilderSupport builder, Object name, Object value, Map attributes) throws InstantiationException, IllegalAccessException
println "newInstance $name $value $attributes"
this.name = name
return new Node(name,value,attributes)
// 在newInstance 之后调用
// 处理属性的方法
@Override
boolean onHandleNodeAttributes(FactoryBuilderSupport builder, Object node, Map attributes)
//如果返回true会从newInstance返回中寻找attributes对应key的属性
return false
// false 表示可以接收闭包
// true 表示不能接收
@Override
boolean isLeaf()
return super.isLeaf()
// 设置当前节点的父节点
@Override
void setParent(FactoryBuilderSupport builder, Object parent, Object child)
super.setParent(builder, parent, child)
println "$name setParent $parent.name $child.name"
// 设置当前节点的子节点
@Override
void setChild(FactoryBuilderSupport builder, Object parent, Object child)
super.setChild(builder, parent, child)
println "$name setChild $parent.name $child.name"
parent.children << child
MyFactoryBuilderSupportTest.groovy
package builder
//new MyFactoryBuilderSupport().xml
//
//
// 会报错,因为我没有注册xml工厂
//五月 16, 2018 10:11:22 下午 groovy.util.FactoryBuilderSupport createNode
//警告: Could not find match for name 'xml'
//Caught: groovy.lang.MissingMethodException: No signature of method: java.lang.Object.xml() is applicable for argument types: (java.util.Collections$EmptyMap, null) values: [[:], null]
//Possible solutions: dump(), any(), wait(), find(), grep(), is(java.lang.Object)
//groovy.lang.MissingMethodException: No signature of method: java.lang.Object.xml() is applicable for argument types: (java.util.Collections$EmptyMap, null) values: [[:], null]
//Possible solutions: dump(), any(), wait(), find(), grep(), is(java.lang.Object)
// at builder.MyFactoryBuilderSupportTest.run(MyFactoryBuilderSupportTest.groovy:5)
//new MyFactoryBuilderSupport().html
//
//
// 不会报错,只是警告 这就是registerFactory 的作用
//五月 16, 2018 10:11:01 下午 groovy.util.FactoryBuilderSupport createNode
//警告: Factory for name 'html' returned null
StringWriter sw = new StringWriter()
new MyFactoryBuilderSupport().html
head('Zeking',key:'value')
.build(sw)
println sw
//newInstance html null [:]
//newInstance head Zeking [key:value]
//head setParent html head
//html setChild html head
//<html><head key='value>Zeking</head></html>
6. FactoryBuilderSupport 和 BuilderSupport 的区别
FactoryBuilderSupport 适用于 固定的方法,必须注册工厂
而BuilderSupport 可以用户高度自定义
FactoryBuilderSupport不适合创建html 但是会非常适合创建swing
以上是关于Groovy12_Jsonxmlswing与生成器的主要内容,如果未能解决你的问题,请参考以下文章