前言
在游戏开发过程中,读取配置文件是必不可少的,而使用JSON做配置文件又比较常见,本文重点给大家讲述如何在Cocos Creator开发中读取和解析JSON数据文件以及如何写JSON文件。
一、JSON简介
1. 什么是JSON
JSON的英文全称是JavaScript Object Notation,即JavaScript对象表示法。
2. JSON的特点
是一种轻量级的文本数据交换格式,类似XML,但是比XML更小、更快、更易解析。使用JavaScript语法来描述数据对象,JS程序无需解析器即可生成原生的JavaScript对象。独立于语言和平台,目前大多数的编程语言都支持JSON。
3. JSON的语法
JSON语法是JavaScript语法的子集,具有以下规则:
数据在名称/值对中
数据由逗号分隔
大括号保存对象
中括号保存数组
二、如何解析JSON文件
1. 关键原则
大括号代表对象,中括号代表数组;
2. 用什么方法读取?
Cocos Creator提供了cc.load.loadRes来专门加载位于 resources 目录下的文件,所以提前把JSON文件放到 asserts/resources 目录下即可。先来一个简单的JSON文件,如下:
1. `// box2dDemo.json`
2. `{`
3. `"engine": "Box2D",`
4. `"version": "2.3.1"`
5. `}`
读取/解析代码如下:
1. `cc.loader.loadRes('box2dDemo.json', function(err, object) {`
2. `if(err) {`
3. `console.log(err);`
4. `return;`
5. `}`
6. `// 读取的数据返回在object中,这是一个拥有2个元素的对象`
7. `let engine = object.engine; // engine = box2D`
8. `let ver = object.version; // ver = 2.3.1`
9. `});`
是不是很简单?实际使用的JSON配置常常比这复杂一些,所以我们现在再给JSON文件增加一些元素,如下:
1. `// box2dDemo.json`
2. `{`
3. `"engine": "Box2D",`
4. `"version": "2.3.1",`
5. `"bodies":`
6. `[`
7. `{`
8. `"name": "root",`
9. `"body":`
10. `{`
11. `"type": "static",`
12. `"gravityScale": 0.2`
13. `}`
14. `},`
15. `{`
16. `"name": "aa1",`
17. `"body":`
18. `{`
19. `"type": "static",`
20. `"gravityScale": 0.2`
21. `}`
22. `}`
23. `],`
24. `"joints":`
25. `[`
26. `{`
27. `"bodyA": "root",`
28. `"bodyB": "aa1",`
29. `"lowerAngle": 0.5,`
30. `"enableLimit": true`
31. `},`
32. `{`
33. `"bodyA": "aa1",`
34. `"bodyB": "aa2",`
35. `"lowerAngle": -0.5,`
36. `"enableLimit": true`
37. `}`
38. `]`
39. `}`
我们在代码中定义一个解析函数叫 readJson,并且把解析出来的JSON数据保存起来,实现代码如下:
1. `readJson: function() {`
2. `this.box2d = {}; // 存储解析出来的JSON数据`
3. `varself= this;`
4. `cc.loader.loadRes('box2dDemo.json', function(err, object) {`
5. `if(err) {`
6. `console.log(err);`
7. `return;`
8. `}`
9. `let engine = object.engine; // engine = box2D`
10. `let ver = object.version; // ver = 2.3.1`
11. `let bodies = object.bodies; // bodies是个数组`
12. `let joints = object.joints; // joints是个数组`
13. `// 需在回调外面提前用self代替this`
14. `self.box2d = object; // box2d是整个对象`
15. `// 将循环2次,因为bodies是个拥有2个对象的数组`
16. `for(let x=0; x < bodies.length; x++) {`
17. `let root = bodies[x]; // root是个对象`
18. `let root_name = root.name; // 第1次循环root_name = root`
19. `let type = root.body.type; // type = static`
20. `let gravity = root.body.gravityScale; // gravity = 0.2`
21. `}`
22. `});`
23. `},`
3. Cocos Creator读取JSON文件注意事项
creator读取json文件的一个坑(对文本内容进行操作可能导致的错误) 使用creator中的 cc.loader.loadRes( url, cc.RawAsset, ( err, res )=>{ } )读取游戏文件后发现第二次进入游戏出现了错误。现对这个问题总结下:对于动态加载资源,第二次读取会直接从缓存中读取,所以如果读取的是一个文本数据,对文本数据修改了,那么相应的,在下一次读取数据会读取修改后的文本数据。比如文本数据就一个数组[1,2,3],第一次读取之后删除了最后一位数据变为为[1,2],那么下一次读取将会是[1,2]。为了不出现这种情况,可以对数据进行序列化与反序列化操作,将其深度拷贝后使用。
4. JSON读取通用代码示例
1. `cc.loader.load(cc.url.raw('resources/data.json'), function(err,res){`
2. `if(err) {`
3. `cc.log(err);`
4. `}else{`
5. `let list=res;`
6. `cc.log("load:");`
7. `cc.log("list:"+list.name);`
8. `}`
9. `});`
10. `// louadRes()方法,默认路径就是resources`
11. `cc.loader.loadRes('data', function(err,res){`
12. `if(err) {`
13. `cc.log(err);`
14. `}else{`
15. `let list=res;`
16. `cc.log("loadRes:");`
17. `cc.log("list:"+list.sex);`
18. `}`
19. `});`
注意:当使用以上代码还报文件不存在或Download text failed的错,那就要检查下资源管理器里是不是有两个resources文件夹,其中一个是最近新建的,另一个可能是以前新建的但是被删除过,但是删除不彻底,因为cocos creator里面的资源都是有一个唯一标识的uuid,所以,还必须找到E:\Projects\你的项目\library\uuid-to-mtime.json这个文件,在里面找到之前的resources文件uuid,先剪切放到文本文件,然后保存uuid-to-mtime.json,重启软件,看是否能进去,不能的话再把剪切出来的uuid复制回去,再重启就可以了。
三、Json文件的写入
1. `// writeToFile()写入数据到文件,存储格式为xml,不是Json格式`
2. `if(cc.sys.isNative) {`
3. `cc.log("Path:"+jsb.fileUtils.getWritablePath()); cc.log( jsb.fileUtils.writeToFile({"new":"value"},jsb.fileUtils.getWritablePath()+'data.json'));`
4. `cc.log("fullPathForFilename:"+jsb.fileUtils.fullPathForFilename("resources/data.json"));`
5. `}`
6. `// writeStringToFile()写入数据到文件,存储格式为json,读取数据用load()方法`
7. `cc.log("writeStringToFile:"+jsb.fileUtils.writeStringToFile('{"a":"b","c":"d"}', jsb.fileUtils.getWritablePath()+'kk.json'));`
8. `cc.log("getValueMapFromFile:"+JSON.stringify(jsb.fileUtils.getValueMapFromFile(jsb.fileUtils.getWritablePath()+"kk.json")));`
`var`
9. `arry=JSON.stringify(jsb.fileUtils.getStringFromFile(jsb.fileUtils.getWritablePath()+"kk.json"));`
10. `cc.log("arry:"+arry);`
11. `cc.loader.load(jsb.fileUtils.getWritablePath()+"kk.json", function(err,res){`
12. `if(err) {`
13. `cc.log(err);`
14. `}else{`
15. `let list=res;`
16. `cc.log("list:"+list.a);`
17. `}`
18. `});`