Groovy
概述
Groovy是一种基于JVM的面向对象语言,如果不声明public/private等访问权限的话,Groovy中类及其变量默认都是public的。
Groovy中有以下特点:
同时支持静态和动态类型
支持运算符重载
对正则表达式的本地支持
可以使用现有的Java库及Java语法
不需要分号
可省略return关键字,默认用最后一个表达式为返回
使用命名的参数初始化beans和默认的构造器:
new Server(name: "Obelix", cluster: aCluster)
Groovy里的
is()
方法等同于Java里的==
,Groovy中的==
是更智能的equals()
在同一个bean中使用with()来重复某一个操作:
// Java server.name = application.name server.status = status server.sessionCount = 3 server.start() server.stop() // Groovy server.with { name = application.name status = status sessionCount = 3 start() stop() }
基本语法
class Test {
static void main(String[] args) {
println('Hello World.')
}
}
在Groovy中下列包是默认导入的:
import java.lang.*
import java.util.*
import java.io.*
import java.net.*
import groovy.lang.*
import groovy.util.*
import java.math.BigInteger
import java.math.BigDecimal
Groovy中使用def来定义变量。
数据类型
内置数据类型
- byte -这是用来表示字节值。例如2。
- short -这是用来表示一个短整型。例如10。
- int -这是用来表示整数。例如1234。
- long -这是用来表示一个长整型。例如10000090。
- float -这是用来表示32位浮点数。例如12.34。
- double -这是用来表示64位浮点数,这些数字是有时可能需要的更长的十进制数表示。例如12.3456565。
- char -这定义了单个字符文字。例如“A”。
- Boolean -这表示一个布尔值,可以是true或false。
- String -这些是以字符串的形式表示的文本。
Groovy提供了多种表示String字面量的方法。 Groovy中的字符串可以用单引号(’),双引号(“)或三引号(”“”)括起来。此外,由三重引号括起来的Groovy字符串可以跨越多行。
Groovy中的字符串是字符的有序序列,字符串索引从零开始,还允许负索引从字符串的末尾开始计数。
class Example {
static void main(String[] args) {
String sample = "Hello world";
println(sample[4]); // Print the 5 character in the string
//Print the 1st character in the string starting from the back
println(sample[-1]);
println(sample[1..2]);//Prints a string starting from Index 1 to 2
println(sample[4..2]);//Prints a string starting from Index 4 back to 2
}
}
对象类型(包装器类型)
- java.lang.Byte
- java.lang.Short
- java.lang.Integer
- java.lang.Long
- java.lang.Float
- java.lang.Double
- 父类为Number
Groovy中的变量可以通过两种方式定义: 使用数据类型的语法,或者使用def关键字。对于变量定义,必须明确提供类型名称或在替换中使用“def”。
class Example {
static void main(String[] args) {
//Example of a int datatype
int x = 5;
//Example of a long datatype
long y = 100L;
//Example of a floating point datatype
float a = 10.56f;
//Example of a double datatype
double b = 10.5e40;
//Example of a BigInteger datatype
BigInteger bi = 30g;
//Example of a BigDecimal datatype
BigDecimal bd = 3.5g;
println(x);
println(y);
println(a);
println(b);
println(bi);
println(bd);
}
}
运算符
Groovy语言支持正常的算术运算符任何语言。
范围运算符:
def range = 5..10;
println(range.get(3))
范围由序列中的第一个和最后一个值表示,Range可以是包含或排除。包含范围包括从第一个到最后一个的所有值,而独占范围包括除最后一个之外的所有值。
- 1..10 - 包含范围的示例
- 1..<10 - 独占范围的示例
- ‘a’..’x’ - 范围也可以由字符组成
- 10..1 - 范围也可以按降序排列
- ‘x’..’a’ - 范围也可以由字符组成并按降序排列。
可通过list[index]方式访问。
方法 | 用法 |
---|---|
contains() | 检查范围是否包含特定值 |
get() | 返回此范围中指定位置处的元素。 |
getFrom() | 获得此范围的下限值。 |
getTo() | 获得此范围的上限值。 |
isReverse() | 这是一个反向的范围,反向迭代 |
size() | 返回此范围的元素数。 |
subList() | 返回此指定的fromIndex(包括)和toIndex(排除)之间的此范围部分的视图 |
循环
语句 | 描述 |
---|---|
while | 首先通过计算条件表达式(布尔值)来执行,如果结果为真,则执行while循环中的语句。 |
for | 用于遍历一组值。 |
for-in | 用于遍历一组值。 |
break | 用于改变循环和switch语句内的控制流。 |
continue | 补充了break语句。它的使用仅限于while和for循环。 |
方法
Groovy中的方法是使用返回类型或使用def关键字定义的。方法可以接收任意数量的参数。定义参数时,不必显式定义类型,可以给参数使用初始值。可以添加修饰符,如public,private和protected。默认情况下,如果未提供可见性修饰符,则该方法为public。
最简单的方法是没有参数的方法,如下所示:
class Example {
static def DisplayName() {
println("This is how methods work in groovy");
println("This is an example of a simple method");
}
static void main(String[] args) {
DisplayName();
}
}
以下是使用参数的简单方法的示例
class Example {
static void sum(int a,int b) {
int c = a+b;
println(c);
}
// 或
static void sum(a, b) {
int c = a + b;
println(c);
}
static void main(String[] args) {
sum(10,5);
}
}
Groovy中还有一个规定来指定方法中的参数的默认值。 如果没有值传递给参数的方法,则使用缺省值。 如果使用非默认和默认参数,则必须注意,默认参数应在参数列表的末尾定义。
以下是使用参数的简单方法的示例:
class Example {
static void sum(int a, int b = 5) {
int c = a + b;
println(c);
}
static void main(String[] args) {
sum(6);
}
}
I/O
Groovy在使用I/O时提供了许多辅助方法,同时也可以使用Java原生IO类。
读取文件
以下示例将输出Groovy中的文本文件的所有行。方法eachLine内置在Groovy中的File类中,目的是确保文本文件的每一行都被读取。
import java.io.File
class Example {
static void main(String[] args) {
new File("E:/Example.txt").eachLine {
line -> println "line : $line";
}
}
}
如果要将文件的整个内容作为字符串获取,可以使用文件类的text属性,即:String s = file.text
。
写入文件
如果想写入文件,则需要使用Write类输出文本到一个文件中:
import java.io.File
class Example {
static void main(String[] args) {
new File('E:/','Example.txt').withWriter('utf-8') {
writer -> writer.writeLine 'Hello World'
}
}
}
获取文件的大小
如果要获取文件的大小,可以使用文件类的length属性来获取:
class Example {
static void main(String[] args) {
File file = new File("E:/Example.txt")
println "The file ${file.absolutePath} has ${file.length()} bytes"
}
}
文件是否是目录
如果要查看路径是文件还是目录,可以使用File类的isFile和isDirectory选项:
class Example {
static void main(String[] args) {
def file = new File('E:/')
println "File? ${file.isFile()}"
println "Directory? ${file.isDirectory()}"
}
}
创建目录
如果要创建一个新目录,可以使用File类的mkdir函数:
class Example {
static void main(String[] args) {
def file = new File('E:/Directory')
file.mkdir()
}
}
删除文件
如果要删除文件,可以使用File类的delete功能:
class Example {
static void main(String[] args) {
def file = new File('E:/Example.txt')
file.delete()
}
}
复制文件
Groovy还提供将内容从一个文件复制到另一个文件的功能:
class Example {
static void main(String[] args) {
def src = new File("E:/Example.txt")
def dst = new File("E:/Example1.txt")
dst << src.text
}
}
获取目录内容
Groovy还提供了列出驱动器中的驱动器和文件的功能,以下示例显示如何使用File类的listRoots函数显示机器上的驱动器:
class Example {
static void main(String[] args) {
def rootFiles = new File("test").listRoots()
rootFiles.each {
file -> println file.absolutePath
}
}
}
以下示例显示如何使用File类的eachFile函数列出特定目录中的文件:
class Example {
static void main(String[] args) {
new File("E:/Temp").eachFile() {
file->println file.getAbsolutePath()
}
}
}
如果要递归显示目录及其子目录中的所有文件,则可以使用File类的eachFileRecurse函数:
class Example {
static void main(String[] args) {
new File("E:/temp").eachFileRecurse() {
file -> println file.getAbsolutePath()
}
}
}
List
- [11,12,13,14] - 整数值列表
- [‘Angular’,’Groovy’,’Java’] - 字符串列表
- [1,2,[3,4],5] - 嵌套列表
- [‘Groovy’,21,2.11] - 异构的对象引用列表
- [] - 空列表
可通过list[index]方式访问。
方法 | 用法 |
---|---|
add() | 将新值附加到此列表的末尾。 |
contains() | 如果此列表包含指定的值,则返回true。 |
get() | 返回此列表中指定位置的元素。 |
isEmpty() | 如果此列表不包含元素,则返回true |
minus() | 创建一个由原始元素组成的新列表,而不是集合中指定的元素。 |
plus() | 创建由原始元素和集合中指定的元素组成的新列表。 |
pop() | 从此列表中删除最后一个项目 |
remove() | 删除此列表中指定位置的元素。 |
reverse() | 创建与原始列表的元素相反的新列表 |
size() | 获取此列表中的元素数。 |
sort() | 返回原始列表的排序副本。 |
多重赋值和多返回值:
// def(var1, var2, var3) = [value1, value2, value3]
def (a, b, c) = fun()
def fun() {
// ...
return [f1, f2, f3]
}
Map
- [‘TopicName’: ‘Lists’, ‘TopicName’: ‘Maps’] - 具有TopicName作为键的键值对的集合及其相应的值。
- [:] - 空映射。
方法 | 用法 |
---|---|
containsKey() | 此映射是否包含此键 |
get() | 查找此Map中的键并返回相应的值。如果此映射中没有键的条目,则返回null。 |
keySet() | 获取此映射中的一组键。 |
put() | 将指定的值与此映射中的指定键相关联。如果此映射先前包含此键的映射,则旧值将替换为指定的值。 |
size() | 返回此地图中的键值映射的数量。 |
values() | 返回此地图中包含的值的集合视图。 |
键可以是任意类型:
def m = [1: 2, 2: 3]
println(m.get(2))
Date
class Example {
static void main(String[] args) {
Date date = new Date();
// 分配一个Date对象并初始化它,以便它表示分配的时间,以最近的毫秒为单位。
System.out.println(date.toString());
}
}
-> output:
Thu Dec 10 21:31:15 GST 2015
class Example {
static void main(String[] args) {
Date date = new Date(100);
// 分配一个Date对象并将其初始化以表示自标准基准时间(称为“该历元”,即1970年1月1日,00:00:00 GMT)起指定的毫秒数。
System.out.println(date.toString());
}
}
->output:
Thu Jan 01 04:00:00 GST 1970
下面是一些常用方法:
方法 | 作用 |
---|---|
after() | 测试此日期是否在指定日期之后。 |
equals() | 比较两个日期的相等性。当且仅当参数不为null时,结果为true,并且是表示与该对象时间相同的时间点(毫秒)的Date对象。 |
compareTo() | 比较两个日期的顺序。 |
toString() | 将此Date对象转换为字符串 |
before() | 测试此日期是否在指定日期之前。 |
getTime() | 返回自此Date对象表示的1970年1月1日,00:00:00 GMT以来的毫秒数。 |
setTime() | 设置此Date对象以表示一个时间点,即1970年1月1日00:00:00 GMT之后的时间毫秒。 |
regex
Groovy使用〜“regex”表达式本地支持正则表达式,引号中包含的文本表示用于比较的表达式:
def regex = ~'Groovy'
字符 | 说明 | |
---|---|---|
\ | 将下一字符标记为特殊字符、文本、反向引用或八进制转义符。例如,”n”匹配字符”n”。”\n”匹配换行符。序列”\\“匹配”\“,”(“匹配”(“。 | |
^ | 匹配输入字符串开始的位置。如果设置了 RegExp 对象的 Multiline 属性,^ 还会与”\n”或”\r”之后的位置匹配。 | |
$ | 匹配输入字符串结尾的位置。如果设置了 RegExp 对象的 Multiline 属性,$ 还会与”\n”或”\r”之前的位置匹配。 | |
* | 零次或多次匹配前面的字符或子表达式。例如,zo 匹配”z”和”zoo”。 等效于 {0,}。 | |
+ | 一次或多次匹配前面的字符或子表达式。例如,”zo+”与”zo”和”zoo”匹配,但与”z”不匹配。+ 等效于 {1,}。 | |
? | 零次或一次匹配前面的字符或子表达式。例如,”do(es)?”匹配”do”或”does”中的”do”。? 等效于 {0,1}。 | |
{n} | n 是非负整数。正好匹配 n 次。例如,”o{2}”与”Bob”中的”o”不匹配,但与”food”中的两个”o”匹配。 | |
{n,} | n 是非负整数。至少匹配 n 次。例如,”o{2,}”不匹配”Bob”中的”o”,而匹配”foooood”中的所有 o。”o{1,}”等效于”o+”。”o{0,}”等效于”o*”。 | |
{n,m} | M 和 n 是非负整数,其中 n <= m。匹配至少 n 次,至多 m 次。例如,”o{1,3}”匹配”fooooood”中的头三个 o。’o{0,1}’ 等效于 ‘o?’。注意:您不能将空格插入逗号和数字之间。 | |
? | 当此字符紧随任何其他限定符(*、+、?、{n}、{n,}、{n,m})之后时,匹配模式是”非贪心的”。”非贪心的”模式匹配搜索到的、尽可能短的字符串,而默认的”贪心的”模式匹配搜索到的、尽可能长的字符串。例如,在字符串”oooo”中,”o+?”只匹配单个”o”,而”o+”匹配所有”o”。 | |
. | 匹配除”\r\n”之外的任何单个字符。若要匹配包括”\r\n”在内的任意字符,请使用诸如”[\s\S]”之类的模式。 | |
x\ | y | 匹配 x 或 y。例如,’z |
[xyz] | 字符集。匹配包含的任一字符。例如,”[abc]”匹配”plain”中的”a”。 | |
xyz | 反向字符集。匹配未包含的任何字符。例如,”abc”匹配”plain”中”p”,”l”, “i”,”n”。 | |
[a-z] | 字符范围。匹配指定范围内的任何字符。例如,”[a-z]”匹配”a”到”z”范围内的任意小写字母。 | |
a-z | 反向范围字符。匹配不在指定的范围内的任何字符。例如,”a-z”匹配任何不在”a”到”z”范围内的任何字符。 | |
\b | 匹配一个字边界,即字与空格间的位置。例如,”er\b”匹配”never”中的”er”,不匹配”verb”中的”er”。 | |
\B | 非字边界匹配。”er\B”匹配”verb”中的”er”,但不匹配”never”中的”er”。 | |
\cx | 匹配 x 指示的控制字符。例如,\cM 匹配 Control-M 或回车符。x 的值必须在A-Z 或 a-z 之间。如果不是这样,则假定 c 就是”c”字符本身。 | |
\d | 数字字符匹配。等效于 [0-9]。 | |
\D | 非数字字符匹配。等效于 0-9。 | |
\f | 换页符匹配。等效于 \x0c 和 \cL。 | |
\n | 换行符匹配。等效于 \x0a 和 \cJ。 | |
\r | 匹配一个回车符。等效于 \x0d 和 \cM。 | |
\s | 匹配任何空白字符,包括空格、制表符、换页符等。与 [ \f\n\r\t\v] 等效。 | |
\S | 匹配任何非空白字符。与 \f\n\r\t\v 等效。 | |
\t | 制表符匹配。与 \x09 和 \cI 等效。 | |
\v | 垂直制表符匹配。与 \x0b 和 \cK 等效。 | |
\w | 匹配任何字类字符,包括下划线。与”[A-Za-z0-9_]”等效。 | |
\W | 与任何非单词字符匹配。与”A-Za-z0-9_”等效。 |
面向对象
Groovy中的面向对象与Java很类似。
特征
特征是语言的结构构造,允许:
- 行为的组成。
- 接口的运行时实现。
- 与静态类型检查/编译的兼容性
它们可以被看作是承载默认实现和状态的接口,使用trait关键字定义trait。
class Test {
static void main(String[] args) {
Student s = new Student()
s.id = 20
s.age = 10
println(s.id)
println(s.age)
s.total()
s.test1()
s.test2()
s.test3()
}
}
interface Total {
void total()
}
trait Marks implements Total {
void test1() {
println('Marks')
}
void total() {
println('total')
}
}
trait Marks1 extends Marks {
int age;
void test2() {
println('Marks1 = ' + age)
}
}
trait Marks2 {
void test3() {
println('Marks2')
}
}
class Student implements Marks1, Marks2 {
int id
}
闭包
概述
闭包是一个短的匿名代码块。它通常跨越几行代码。一个方法甚至可以将代码块作为参数。它们是匿名的。
static void main(String[] args) {
def clos = {println "Hello World"};
clos.call();
clos();
}
在Groovy中,每个闭包都是groovy.lang.Closure的实例,执行闭包对象有两种,一是直接用括号+参数,二是调用call方法+参数。
闭包的形参
static void main(String[] args) {
def clos = {param -> println "Hello ${param}"};
clos.call("World");
}
static void main(String[] args) {
def clos = {println "Hello ${it}"};
clos.call("World");
}
闭包和变量
闭包可以在定义闭包时引用变量。
static void main(String[] args) {
def str1 = "Hello";
def clos = {param -> println "${str1} ${param}"}
clos.call("World");
// We are now changing the value of the String str1 which is referenced in the closure
str1 = "Welcome";
clos.call("World");
}
->output:
Hello World
Welcome World
在方法中使用闭包
以下示例显示如何将闭包作为参数发送到方法。
class Example {
def static Display(clo) {
// This time the $param parameter gets replaced by the string "Inner"
clo.call("Inner");
}
static void main(String[] args) {
def str1 = "Hello";
def clos = { param -> println "${str1} ${param}" }
clos.call("World");
// We are now changing the value of the String str1 which is referenced in the closure
str1 = "Welcome";
clos.call("World");
// Passing our closure to a method
Example.Display(clos);
}
}
->output:
Hello World
Welcome World
Welcome Inner
def filter(array, block) {
for (val in array) {
block(val)
}
}
iarray = [1, 2, 3, 4, 5, 6, 7, 8, 9]
total = []
filter(iarray, { if (it % 2 == 0) total << it })
println total // [2, 4, 6, 8]
total = []
filter(iarray, { if (it > 5) total << it })
println total // [6, 7, 8, 9]
当闭包作为最后一个参数时,可以有其它写法
filter(iarray) { if (it % 2 == 0) total << it }
集合和字符串中的闭包
List,Map和String方法接受一个闭包作为参数。
class Example {
static void main(String[] args) {
def lst = [11, 12, 13, 14];
lst.each {println it}
}
}
class Example {
static void main(String[] args) {
def mp = ["TopicName" : "Maps", "TopicDescription" : "Methods in Maps"]
mp.each {println it}
mp.each {println "${it.key} maps to: ${it.value}"}
}
}
class Example {
static void main(String[] args) {
def lst = [1,2,3,4];
lst.each {println it}
println("The list will only display those numbers which are divisible by 2")
lst.each{num -> if(num % 2 == 0) println num}
}
}
方法
方法 | 用法 |
---|---|
find() | find方法查找集合中与某个条件匹配的第一个值。 |
findAll() | 它找到接收对象中与闭合条件匹配的所有值。 |
any() & every() | 方法any迭代集合的每个元素,检查布尔谓词是否对至少一个元素有效。 |
collect() | 该方法通过集合收集迭代,使用闭包作为变换器将每个元素转换为新值。 |
闭包委托
在闭包内部,有三个内置对象this,owner,delegate,我们可以直接this,owner,delegate调用,或者用get方法:
- getThisObject() 等于 this
- getOwner() 等于 owner
- getDelegate() 等于delegate
- this 该属性指向定义闭包的类的实例对象
- owner 该属性和 this 类似,但是闭包中也可以定义闭包的,如果闭包 A 内定义了闭包 B,那么闭包 B 的 owner 指向的是其外部的闭包 A
- delegate 该值初始化时是和 owner 相同的,但是该值可以通过接口将其它对象赋值给 delegate,来实现方法的委托功能
class Hello {
static void main(String[] args) {
def p = new Person(name: "hearing")
p.clo()
}
}
class Person {
String name
def clo = {
println(name)
// 都有.name属性
println(this)
println(owner)
println(delegate)
def clo1 = {
println(name)
println(this)
// 没有.name属性
println(owner)
println(delegate)
}
clo1.delegate = Person
clo1()
}
}
->output:
hearing
Person@35d176f7
Person@35d176f7
Person@35d176f7
hearing
Person@35d176f7
Person$_closure1@6ebc05a6
class Person
设置delegate的意义就是将闭包和一个具体的对象关联起来,在闭包中可以访问被代理对象的属性和方法,如果闭包所在的类或闭包中和被代理的类中有相同名称的方法,那么有几种代理策略:
- Closure.OWNER_FIRST是默认策略。优先在owner寻找,owner没有再delegate
- Closure.DELEGATE_FIRST:优先在delegate寻找,delegate没有再owner
- Closure.OWNER_ONLY:只在owner中寻找
- Closure.DELEGATE_ONLY:只在delegate中寻找
- Closure.TO_SELF:
用法实例:
# Person.groovy
class Person {
String name
int age
void eat(String food) {
println("你喂的${food}真难吃")
}
@Override
String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}'
}
}
# Main.groovy
class Main {
void eat(String food){
println "我根本不会吃,不要喂我${food}"
}
def cc = {
name = "hanmeimei"
age = 26
eat("油条")
}
static void main(String... args) {
Main main = new Main()
Person person = new Person(name: "lilei", age: 14)
println person.toString()
main.cc.delegate = person
// main.cc.setResolveStrategy(Closure.DELEGATE_FIRST)
main.cc.setResolveStrategy(Closure.OWNER_FIRST)
main.cc.call()
println person.toString()
}
}
DSL(领域定义语言)
class Gradle {
String type
String version
String result
def type(type) {
this.type = type
}
def version(version) {
this.version = version
}
def result(str) {
result = version + type
println str + result
}
static def build(closure) {
Gradle gradle = new Gradle()
closure.delegate = gradle
closure.call()
}
}
Gradle.build {
type 'compile'
version '1.11 '
result 'build: '
}
-> output
// build: 1.11 compile
Groovy XML
概述
Groovy语言提供了对XML语言的丰富支持,其两个最基本的XML类是:
- XML生成器:
groovy.xml.MarkupBuilder
- XML解析器:
groovy.util.XmlParser
MarkupBuilder
import groovy.xml.MarkupBuilder
class Example {
static void main(String[] args) {
def mp = [1 : ['Enemy Behind', 'War, Thriller','DVD','2003',
'PG', '10','Talk about a US-Japan war'],
2 : ['Transformers','Anime, Science Fiction','DVD','1989',
'R', '8','A scientific fiction'],
3 : ['Trigun','Anime, Action','DVD','1986',
'PG', '10','Vash the Stam pede'],
4 : ['Ishtar','Comedy','VHS','1987', 'PG',
'2','Viewable boredom ']]
def mB = new MarkupBuilder()
// Compose the builder
def MOVIEDB = mB.collection('shelf': 'New Arrivals') {
mp.each { sd ->
mB.movie('title': sd.value[0]) {
type(sd.value[1])
format(sd.value[2])
year(sd.value[3])
rating(sd.value[4])
stars(sd.value[4])
description(sd.value[5])
}
}
}
}
}
运行上面代码会生成如下XML内容:
<collection shelf='New Arrivals'>
<movie title='Enemy Behind'>
<type>War, Thriller</type>
<format>DVD</format>
<year>2003</year>
<rating>PG</rating>
<stars>PG</stars>
<description>10</description>
</movie>
<movie title='Transformers'>
<type>Anime, Science Fiction</type>
<format>DVD</format>
<year>1989</year>
<rating>R</rating>
<stars>R</stars>
<description>8</description>
</movie>
<movie title='Trigun'>
<type>Anime, Action</type>
<format>DVD</format>
<year>1986</year>
<rating>PG</rating>
<stars>PG</stars>
<description>10</description>
</movie>
<movie title='Ishtar'>
<type>Comedy</type>
<format>VHS</format>
<year>1987</year>
<rating>PG</rating>
<stars>PG</stars>
<description>2</description>
</movie>
</collection>
XmlParser
对于上面的XML,可以使用下述方法解析:
import groovy.xml.MarkupBuilder
import groovy.util.*
class Example {
static void main(String[] args) {
def parser = new XmlParser()
def doc = parser.parse("Movies.xml");
doc.movie.each{ bk->
print("Movie Name:")
println "${bk['@title']}"
print("Movie Type:")
println "${bk.type[0].text()}"
print("Movie Format:")
println "${bk.format[0].text()}"
print("Movie year:")
println "${bk.year[0].text()}"
print("Movie rating:")
println "${bk.rating[0].text()}"
print("Movie stars:")
println "${bk.stars[0].text()}"
print("Movie description:")
println "${bk.description[0].text()}"
println("*******************************")
}
}
}
运行上面的程序可以得到以下结果:
Movie Name:Enemy Behind
Movie Type:War, Thriller
Movie Format:DVD
Movie year:2003
Movie rating:PG
Movie stars:10
Movie description:Talk about a US-Japan war
*******************************
Movie Name:Transformers
Movie Type:Anime, Science Fiction
Movie Format:DVD
Movie year:1989
Movie rating:R
Movie stars:8
Movie description:A schientific fiction
*******************************
Movie Name:Trigun
Movie Type:Anime, Action
Movie Format:DVD
Movie year:1986
Movie rating:PG
Movie stars:10
Movie description:Vash the Stam pede!
*******************************
Movie Name:Ishtar
Movie Type:Comedy
Movie Format:VHS
Movie year:1987
Movie rating:PG
Movie stars:2
Movie description:Viewable boredom
Groovy JSON
概述
Groovy语言提供了两个类来处理JSON格式的数据:
- JSON生成器:
groovy.json.JsonOutput
- JSON解析器:
groovy.json.JsonSlurper
JsonOutput
- 用法:
Static string JsonOutput.toJson(datatype obj)
。 - 参数:可以是数据类型的对象,数字,布尔,字符,字符串,日期,地图,闭包等。
- 返回类型:一个JSON字符串。
import groovy.json.JsonOutput
class Example {
static void main(String[] args) {
def output = JsonOutput.toJson([name: 'John', ID: 1])
println(output);
}
}
以上程序的输出如下:
{"name":"John","ID":1}
JsonOutput也可以用于普通的Groovy对象:
import groovy.json.JsonOutput
class Example {
static void main(String[] args) {
def output = JsonOutput.toJson([ new Student(name: 'John', ID: 1), new Student(name: 'Mark', ID: 2)])
println(output);
}
}
class Student {
String name
int ID;
}
以上程序的输出如下:
[{"name":"John","ID":1},{"name":"Mark","ID":2}]
JsonSlurper
JsonSlurper是一个将JSON文本或阅读器内容解析为Groovy数据结构的类,如Map,列表和原始类型,如Integer,Double,Boolean和String等。
- 用法:
def slurper = new JsonSlurper()
JsonSlurper类自带了一些用于解析器实现的变体,例如当读取从Web服务器的响应返回的JSON时使用解析器JsonParserLax变量是有益的,此parser允许在JSON文本中存在注释以及没有引号字符串等。要指定此类型的解析器需要在定义JsonSlurper的对象时使用JsonParserType.LAX解析器类型。
http.request( GET, TEXT ) {
headers.Accept = 'application/json'
headers.'User-Agent' = USER_AGENT
response.success = {
res, rd ->
def jsonText = rd.text
//Setting the parser type to JsonParserLax
def parser = new JsonSlurper().setType(JsonParserType.LAX)
def jsonResp = parser.parseText(jsonText)
}
}
类似地,以下附加的解析器类型在Groovy中可用:
- JsonParserCharArray解析器基本上采用一个JSON字符串并对底层字符数组进行操作。在值转换期间,它复制字符子数组(称为“斩波”的机制)并单独操作它们。
- JsonFastParser是JsonParserCharArray的一个特殊变体,是最快的解析器。JsonFastParser也称为索引覆盖解析器,在解析给定的JSON字符串期间,它尽可能努力地避免创建新的字符数组或String实例。它只保留指向底层原始字符数组的指针。此外,它会尽可能晚地推迟对象创建。
- JsonParserUsingCharacterSource是一个非常大的文件的特殊解析器。它使用一种称为“字符窗口化”的技术来解析具有恒定性能特征的大型JSON文件(大型意味着超过2MB大小的文件)。
文本解析:
import groovy.json.JsonSlurper
class Example {
static void main(String[] args) {
def jsonSlurper = new JsonSlurper()
def object = jsonSlurper.parseText('{ "name": "John", "ID" : "1"}')
println(object.name);
println(object.ID);
}
}
以上程序的输出如下:
John
1
解析整数列表:
我们可以使用每个的List方法,并传递一个闭包。
import groovy.json.JsonSlurper
class Example {
static void main(String[] args) {
def jsonSlurper = new JsonSlurper()
Object lst = jsonSlurper.parseText('{ "List": [2, 3, 4, 5] }')
lst.each { println it }
}
}
以上程序的输出如下:
List=[2, 3, 4, 5, 23, 42]
解析基本数据类型列表:
JSON解析器还支持字符串,数字,对象,true,false和null的原始数据类型。JsonSlurper类将这些JSON类型转换为相应的Groovy类型。
import groovy.json.JsonSlurper
class Example {
static void main(String[] args) {
def jsonSlurper = new JsonSlurper()
def obj = jsonSlurper.parseText ''' {"Integer": 12, "fraction": 12.55, "double": 12e13}'''
println(obj.Integer);
println(obj.fraction);
println(obj.double);
}
}
以上程序的输出如下:
12
12.55
1.2E+14