1. 程式人生 > >Gradle入門系列(二)——groovy高階語法

Gradle入門系列(二)——groovy高階語法

groovy高階語法

一、json操作

使用groovy自帶的json工具進行json操作

groovy.json.JsonSlurper:將json原資料轉成實體物件 groovy.json.JsonOutput:將實體物件轉成json資料

def list = [
  new Person(name: 'John', age: 25),
  new Person(name: 'Major', age: 26)
]

// 物件轉json
def json = JsonOutput.toJson(list)
println json                         // 一行輸出json字串
println JsonOutput.prettyPrint(json) // 以json格式輸出json字串 // json轉物件 def jsonSlurper = new JsonSlurper() jsonSlurper.parse(obj) // jsonSlurper.parseText(str) 複製程式碼

groovy是完全相容java的,所以java能使用的第三方json庫(如:gson、fastjson),在groovy中也同樣可以匯入使用,但一般不建議這麼做,groovy本身提供的工具箱就已經滿足日常開發需求了。

下面是groovy將網路json資料轉成實體物件,並訪問對應屬性欄位的例子:

def response = getNetworkData("http://xxx/data.json")
println response.data.name        // 不需要定義具體的實體類,就可以直接訪問對應的屬性欄位

def getNetworkData(String url){
  // 傳送http請求
  def connection = new URL(url).openConnection()
  connection.setRequestMethod('GET')
  connection.connect() // 該方法會阻塞執行緒
  def response = connection.content.text
  
  // 將json轉化為實體物件
def jsonSluper = new JsonSlurper() return jsonSluper.parseText(response) } 複製程式碼

二、xml檔案操作

java xml處理:DOM文件驅動處理方式、SAX事件驅動處理方式。 groovy則為我們提供了xml工具箱:

groovy.xml.XmlSlurper:將xml原資料轉成實體物件 groovy.xml.MarkupBuilder:將實體物件轉成xml資料

1、解析xml

final String xml = '''
  <response version-api="2.0">
    <value>
      <books id="1" classification="android">
        <book available="20" id="1">
          <title>瘋狂Android講義</title>
          <author id="1">李剛</author>
        </book>
        <book available="14" id="2">
          <title>第一行程式碼</title>
          <author id="2">郭林</author>
        </book>
        <book available="13" id="3">
          <title>Android開發藝術探索</title>
          <author id="3">任玉剛</author>
        </book>
        <book available="5" id="4">
          <title>Android原始碼設計模式</title>
          <author id="4">何紅輝</author>
        </book>
      </books>
      <books id="2" classification="web">
        <book available="10" id="1">
          <title>Vue從入門到精通</title>
          <author id="4">李剛</author>
        </book>
      </books>
    </value>
  </response>
'''

def xmlSlurper = new XmlSlurper() 
def response = xmlSlurper.parseText(xml) // 讀取並解析xml資料

println response.value.books[0].book[0].title.text() // 獲取標籤內容
println response.value.books[0].book[0].@available   // 獲取標籤屬性

// 獲取所有作者是"李剛"的書籍名稱
// 方法一:平行遍歷xml資料
def list = []
response.value.books.each { books ->
  books.book.each { book ->
    def author = book.author.text()
    if(author.equals('李剛')){
      list.add(book.title.text())
    }
  }
}
println list.toListString()
// 方法二:深度遍歷xml資料 
// response.depthFirst().findAll 相當於 response.'**'.findAll
def titles = response.depthFirst().findAll { book ->
  return book.author.text() == '李剛' ? true : false
}

// 獲取id為2的book節點的title內容
// 廣度遍歷xml資料
// response.value.books.children().findAll 相當於 response.value.books.'*'.findAll
def names = response.value.books.children().findAll { node ->
  node.name() == 'book' && node.@id == '2'
}.collect { node ->
  return node.title.text()
}
複製程式碼
李剛
20

[瘋狂Android講義, Vue從入門到精通]
複製程式碼

其他:

  • 深度遍歷 depthFirst()可以使用'**'表示。
  • 廣度遍歷 children()可以使用'*'表示。

2、生成xml

/**
 * 生成xml格式資料
 * <langs type='current' count='3' mainstream='true'>
 * <language flavor='static' version='1.5'>java</language>
 * <language flavor='dynamic' version='1.6.0'>Groovy</language>
 * <language flavor='dynamic' version='1.9'>JavaScript</language>
 * </langs>
 */

def sw = new StringWriter()
def xmlBuilder = new MarkupBuilder(sw) // 用來生成xml資料的核心類
// 使用偽方法建立 根結點langs,在引數括號中指定標籤屬性key-value
xmlBuilder.langs(type: 'current', count: '3', mainstream: 'true'){
  // 同樣,使用偽方法建立 language結點,不指定key時,該value將作為標籤內容
  language(flavor: 'static', version: '1.5', 'Java')
  language(flavor: 'dynamic', version: '1.6.0', 'Groovy')
  language(flavor: 'dynamic', version: '1.9', 'JavaScript')
}
println sw
複製程式碼

上面是使用MarkupBuilder直接編寫輸出xml資料,但實際開發中,往往是將實體物件轉成xml,在明白MarkupBuilder的用法之後,這樣的需求處理也是差不多的:

def sw = new StringWriter()
def xmlBuilder = new MarkupBuilder(sw)
def langs = new Langs()
xmlBuilder.langs(type: langs.type, count: langs.count, mainstream: langs.mainstream) {
  langs.languages.each { lang->
    language (flavor: lang.flavor, version: lang.version, lang.value)
  }
}


class Langs{
  String type = 'current'
  String count = '3'
  String mainstream = 'true'
  def Languages = [
    new Language(flavor: 'static', version: '1.5', value: 'java'),
    new Language(flavor: 'dynamic', version: '1.6.0', value: 'Groovy')
    new Language(flavor: 'dynamic', version: '1.9', value: 'JavaScript')
  ]
}

class Language{
  String flavor
  String version
  String value
}
...
複製程式碼

三、檔案操作

java檔案處理:節點流(InputStream、OutputSteam及其子類)、處理流(Reader、Writer及其子類) groovy檔案處理:所有java對檔案的處理類,groovy都可以使用;groovy擴充套件了許多更加快捷和強大的方法(ResourceGroovyMethods)。

def file = new File('../../GroovySpecification.iml')
file.eachLine { line -> // 遍歷檔案中的每一行
  println line
}
def text = file.getText() // 返回檔案中所有行內容的文字
def result = file.readLines() // 返回一個一行行文字內容的List
def readerBuffer = file.withReader { reader -> // 讀取檔案中前100個字元
  char[] buffer = new char[100]
  reader.read(buffer)
  return buffer
}

// copy檔案
def copy(String srcPath, String destPath) {
  try{
    // 建立目標檔案
    def destFile = new File(destPath)
    if(!destFile.exists()){
      destFile.createNewFile()
    }
    // 開始拷貝
    new File(srcPath).withReader{ reader ->
      def lines = reader.readLines()
      destFile.withWriter{ writer ->
        lines.each{ line ->
          writer.append(line+"\r\n")
        }
      }
    }
  }catch(Exception e){
    e.printStackTrace() 
  }
}

// 物件儲存到檔案
def saveObject(Object object, String path){
  try{
    // 建立目標檔案
    def destFile = new File(path)
    if(!destFile.exists()){
      destFile.createNewFile()
    }
    destFile.withObjectOutputStream { out ->
      out.writeObject(object)
    }
  }catch(Exception e){
    e.printStackTrace()
  }
}

// 從檔案讀取物件
def readObject(String path){
  def obj = null
  try{
    def file = new File(path)
    if(file == null || !file.exists()) return null
    // 從檔案中讀取物件
    file.withObjectInputStream{ input ->
      obj = input.readObject()
    }
  }catch(Exception e){
    e.printStackTrace()
  }
  return obj
}
複製程式碼

四、與java對比及總結

  • 寫法上,沒有java那麼多限制(如:分號、return)
  • 功能上,對java已有的功能進行了極大的擴充套件
  • 作用上,即可以編寫應用,也可以編寫指令碼