抛开关于是否使用JSON作为配置格式的争论,只学习如何使用Groovy解析它。应用程序通常包括某种类型的默认或“开箱即用”状态或配置,以及一些供用户自定义配置以满足其需要的方式。例如,LibreOfficeWriter通过其菜单栏上的工具>选项提供对用户数据、字体、语言设置(以及更多)等设置的访问。某些应用程序(例如LibreOffice)提供点击式用户界面来管理这些设置。有些,如Tracker(GNOME的“任务”,用于索引文件)使用XML文件。还有一些应用程序,尤其是基于JavaScript的应用程序,尽管有许多反对意见,但仍使用JSON(例如,这位作者和另一位作者)。在本文中,我将回避关于是否使用JSON作为配置文件格式的争论,并解释如何使用Groovy编程语言来解析此类信息。Groovy基于Java,但具有一组不同的设计优先级,这使得Groovy感觉更像Python。安装Groovy因为Groovy是基于Java的,所以它也需要安装Java。您可能可以在Linux发行版的软件存储库中找到最新的、合适的Java和Groovy版本。或者,您可以按照其网站上的说明安装Groovy。对于Linux用户来说,一个不错的选择是SDKMan,您可以使用它来获取多个版本的Java、Groovy和许多其他相关工具。对于本文,我将使用我的发行版的OpenJDK11和SDKMan的Groovy3.0.7。演示的JSON配置文件在这个演示中,我从Drupal中获取了这个JSON文件,它是DrupalCMS使用的主要配置文件,并将其保存在文件config.json中:{"vm":{"ip":"192.168.44.44","memory":"1024","synced_folders":[{"host_path":"data/","guest_path":"/var/www","type":"default"}],"forwarded_ports":[]},"vdd":{"sites":{"drupal8":{"account_name":"root","account_pass":"root","account_mail":"box@example.com","site_name":"Drupal8","site_mail":"box@example.com","vhost":{"document_root":"drupal8","url":"drupal8.dev","alias":["www.drupal8.dev"]}},"drupal7":{"account_name":"root","account_pass":"root","account_mail":"box@example.com","site_name":"Drupal7","site_mail":"box@example.com","vhost":{"document_root":"drupal7","url":"drupal7.dev","alias":["www.drupal7.dev"]}}}}}这是一个不错的复杂JSON文件,有多层结构,例如:<>.vdd.sites.drupal8.account_name和一些列表,例如:<>.vm.synced_folders这里,<>代表未命名的顶层。让我们看看Groovy是如何处理它的。使用Groovy解析JSONGroovy附带的groovy.json包中有各种很酷的东西。其中最好的部分是JsonSlurper类,它包括几个将JSON转换为GroovyMap的parse()方法,GroovyMap是一种基于键值存储的数据结构。下面是一个名为config1.groovy的简短Groovy程序,它创建了一个JsonSlurper实例,然后调用其中的parse()方法解析文件中的JSON,将其转换为一个名为config的Map实例,最后设置map输出:importgroovy.json.JsonSlurperdefjsonSlurper=newJsonSlurper()defconfig=jsonSlurper.parse(newFile('config.json'))println"config=$config"在终端的命令行上运行这个程序:$groovyconfig1.groovyconfig=[vm:[ip:192.168.44.44,memory:1024,synced_folders:[[host_path:data/,guest_path:/var/www,type:default]],forwarded_ports:[]],vdd:[站点:[drupal8:[account_name:root,account_pass:root,account_mail:box@example.com,site_name:Drupal8,site_mail:box@example.com,vhost:[document_root:drupal8,url:drupal8.dev,别名:[www.drupal8.dev]]],drupal7:[account_name:root,account_pass:root,account_mail:box@example.com,site_name:Drupal7,site_mail:box@example.com,vhost:[document_root:drupal7,url:drupal7.dev,别名:[www.drupal7.dev]]]]]]$输出显示具有两个键的顶级映射:vm和vdd。每个键都引用它自己的值映射。请注意forwarded_ports键引用的空列表。这很简单,但它所做的只是打印出来。你是如何获得各种组件的?这是另一个显示如何访问存储在config.vm.ip中的值的程序:)println"config.vm.ip=${config.vm.ip}"来运行它:$groovyconfig2.groovyconfig.vm.ip=192.168.44.44$是的,这也很简单。这使用了Groovy简写,这意味着:config.vm.ip在Groovy中等同于:config['vm']['ip']当config和config.vm都是Map的实例时,两者都等同于中的:config.get("vm").get("ip")只是处理JSON,仅此而已。如果你想要一个标准配置并让用户覆盖它怎么办?在这种情况下,您可能希望在程序中硬编码JSON配置,然后读取用户配置并覆盖任何标准配置设置。假设上面的配置是标准的,用户只想覆盖一点,只想覆盖vm结构中的ip和内存值,放在userConfig.json文件中:{"vm":{"ip":"201.201.201.201","memory":"4096",}}你可以用这个程序来做:importgroovy.json.JsonSlurperdefjsonSlurper=newJsonSlurper()//使用parseText()来解析一个字符串而不是从文件中读取。//这给了我们一个“标准配置”defstandardConfig=jsonSlurper.parseText("""{"vm":{"ip":"192.168.44.44","memory":"1024","synced_folders":[{"host_path":"data/","guest_path":"/var/www","type":"default"}],"forwarded_ports":[]},"vdd":{"sites":{"drupal8":{"account_name":"root","account_pass":"root","account_mail":"box@example.com","site_name":"Drupal8","site_mail":"box@example.com","vhost":{"document_root":"drupal8","url":"drupal8.dev","alias":["www.drupal8.dev"]}},"drupal7":{"account_name":"root","account_pass":"root","account_mail":"box@example.com","site_name":"Drupal7","site_mail":"box@example.com","vhost":{"document_root":"drupal7","url":"drupal7.dev","alias":["www.drupal7.dev"]}}}}}"")//打印标准配置println"standardConfig=$standardConfig"//读入并解析用户配置信息defuserConfig=jsonSlurper.parse(newFile('userConfig.json'))//打印出用户配置信息println"userConfig=$userConfig"//一个用户Configure与标准配置合并的函数defmergeMaps(Mapinput,Mapmerge){merge.each{k,v->if(vinstanceofMap)mergeMaps(input[k],v)elseinput[k]=v}}//合并配置并打印出修改后的标准配置mergeMaps(standardConfig,userConfig)println"修改后的标准配置$standardConfig"运行方式如下:ig=[vm:[ip:192.168.44.44,memory:1024,synced_folders:[[host_path:data/,guest_path:/var/www,type:default]],forwarded_ports:[]],vdd:[sites:[drupal8:[account_name:root,account_pass:root,account_mail:box@example.com,site_name:Drupal8,site_mail:box@example.com,vhost:[document_root:drupal8,url:drupal8.dev,别名:[www.drupal8.dev]]],drupal7:[account_name:root,account_pass:root,account_mail:box@example.com,site_name:Drupal7,site_mail:box@example.com,vhost:[document_root:drupal7,url:drupal7.dev,别名:[www.drupal7.dev]]]]]]userConfig=[vm:[ip:201.201.201.201,memory:4096]]修改标准配置[vm:[ip:201.201.201.201,memory:4096,synced_folders:[[host_path:data/,guest_path:/var/www,type:default]],forwarded_ports:[]],vdd:[sites:[drupal8:[account_name:root,account_pass:root,account_mail:box@example.com,site_name:Drupal8,site_mail:box@example.com,vhost:[document_root:drupal8,url:drupal8.dev,别名:[www.drupal8.dev]]],drupal7:[account_name:root,account_pass:root,account_mail:box@example.com,site_name:Drupal7,site_mail:box@example.com,vhost:[document_root:drupal7,url:drupal7.dev,别名:[www.drupal7.dev]]]]]$以修改后的standardConfig开头的行显示vm.ipandvm.memory的值被覆盖眼尖的读者会注意到我没有检查格式错误的JSON或仔细确保用户的配置是Makesense(不要创建新字段,提供合理的值等)。所以用这种递归的方式来合并两张地图在现实中可能并不那么实用。好吧,我得留些作业做作业,不是吗?Groovy资源ApacheGroovy站点有很多很棒的文档。另一个很棒的Groovy资源是Haki先生。学习Groovy的一个很好的理由是转向Grails,这是一个非常高效的全栈Web框架,构建在Hibernate、SpringBoot和Micronaut等优秀组件之上。
