jsonを取得、表示するアプリケーション　その１３

リクエストパラメータの入力をテーブルに変更する
ついでにメニューもつけておく

このアプリケーションについてはとりあえずここまで。
ここから先を作りこむならgriffonに移植するほうがいいかな

```groovy:json_client.groovy
import groovy.swing.SwingBuilder
import groovy.json.JsonOutput
import groovy.json.JsonSlurper
import groovy.beans.Bindable
import javax.swing.*
import javax.swing.tree.DefaultMutableTreeNode as TreeNode
import java.awt.*
import java.net.*

def manager = new CookieManager()
manager.cookiePolicy = CookiePolicy.ACCEPT_ALL
CookieHandler.default = manager

@Bindable
class Model {
	String method = 'GET'
	String url = ''
	String params = ''
	String header = ''
	String json = ''
	Boolean enabled = true
}
def model = new Model()

def tabPane
def paramTable
def dataModel
def jsonTree

class TreeUtil {
	def clearTree = { jsonTree ->
		jsonTree.model.root.removeAllChildren()
		jsonTree.model.reload(jsonTree.model.root)
	}
	
	def createTree = { jsonTree, json ->
		clearTree(jsonTree)
		createNode(jsonTree.model.root, json)
	}
	
	def reloadTree = { jsonTree ->
		jsonTree.model.reload(jsonTree.model.root)
	}
	
	def createNode = { node, json ->
		if (json instanceof HashMap) {
			json.each { key, value ->
				def childNode = new TreeNode(key)
				node.add(childNode)
				createNode(childNode, value)
			}
		} else if (json instanceof ArrayList) {
			json.eachWithIndex { child, index ->
				def childNode = new TreeNode(index + 1)
				node.add(childNode)
				createNode(childNode, child)
			}
		} else {
			node.add(new TreeNode(json))
		}
	}
}
def treeUtil = new TreeUtil()

def prettyPrint = { text ->
	def result = JsonOutput.prettyPrint(text)
	(result =~ /\\u[0-9a-zA-Z]{4}/).each { match ->
		def code = match[2..5]
		def encTxt = new String([Integer.parseInt(code, 16)] as int[], 0, 1)
		result = result.replaceAll(/\\u${code}/, encTxt)
	}
	result
}

def swing = new SwingBuilder()

def sendRequest = {
	model.header = ''
	model.json = ''
	model.enabled = false
	treeUtil.clearTree(jsonTree)
	
	swing.doOutside {
		def method = model.method
		def url = model.url
		def params = new StringBuilder()
		dataModel.rows.each { row ->
			if (row.name.size() == 0) return
			if (params.size() > 0) params << '&'
			params << "${row.name}=${URLEncoder.encode(row.value, 'utf-8')}"
		}
		println params
		if (method == 'GET') {
			url = "${url}?${params}"
		}
		println url
		
		def conn = url.toURL().openConnection()
		conn.requestMethod = method
		if (method == 'POST') {
			conn.doOutput = true
			conn.outputStream << params
		}
		
		def header = new StringBuilder()
		conn.headerFields.each { key, fields ->
			fields.each { field ->
				header << "${key ? key + ':' : ''}${field}\n"
			}
		}
		model.header = header.toString()
		
		model.json = prettyPrint(conn.inputStream.getText('utf-8'))
		
		def json = new JsonSlurper().parseText(model.json)
		treeUtil.createTree(jsonTree, json)
		
		conn.disconnect()
		
		doLater {
			treeUtil.reloadTree(jsonTree)
			
			tabPane.selectedIndex = 2
			model.enabled = true
		}
	}
}

swing.edt {
	frame(title:'jsonを取得、表示するアプリケーション', defaultCloseOperation:JFrame.EXIT_ON_CLOSE,
			size: [800, 600], show:true) {
		lookAndFeel('nimbus')
		borderLayout()
		menuBar() {
			menu(text:'ファイル', mnemonic:'F') {
				menuItem(text:'終了', mnemonic:'X', actionPerformed:{dispose()})
			}
		}
		hbox(constraints: BorderLayout.NORTH) {
			comboBox(items:['GET', 'POST'], selectedItem:bind(source: model, sourceProperty: 'method', mutual: true))
			textField(text:bind(source: model, sourceProperty: 'url', mutual: true))
			button(text:'送信', actionPerformed:sendRequest, enabled:bind {model.enabled})
		}
		tabPane = tabbedPane(constraints: BorderLayout.CENTER) {
			panel(name:'パラメータ') {
				borderLayout()
				hbox(constraints: BorderLayout.NORTH) {
					button(text:'追加', actionPerformed:{
						dataModel.rows.add([name:'', value:''])
						dataModel.fireTableDataChanged()
					})
					button(text:'削除', actionPerformed:{
						if (paramTable.selectedRow == -1) return
						dataModel.rows.remove(paramTable.selectedRow)
						dataModel.fireTableDataChanged()
					})
				}
				scrollPane() {
					paramTable = table(constraints: BorderLayout.CENTER, autoResizeMode:JTable.AUTO_RESIZE_OFF) {
						dataModel = tableModel {
							propertyColumn(header:'名前', propertyName:'name')
							propertyColumn(header:'値', propertyName:'value')
						}
					}
					paramTable.putClientProperty('terminateEditOnFocusLost', true)
				}
			}
			scrollPane(name:'ヘッダ') {
				textArea(editable:false, text:bind {model.header})
			}
			scrollPane(name:'レスポンス（テキスト）') {
				textArea(editable:false, text:bind {model.json})
			}
			scrollPane(name:'レスポンス（ツリー）') {
				jsonTree = tree(rootVisible: false)
				treeUtil.clearTree(jsonTree)
			}
		}
		progressBar(constraints: BorderLayout.SOUTH, indeterminate:bind{!model.enabled})
	}
}
```

![qiita-013.png](https://qiita-image-store.s3.amazonaws.com/0/17179/b3280266-0b18-f447-b9ff-f6640eb824f9.png)