index.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. var _fs
  2. try {
  3. _fs = require('graceful-fs')
  4. } catch (_) {
  5. _fs = require('fs')
  6. }
  7. function readFile (file, options, callback) {
  8. if (callback == null) {
  9. callback = options
  10. options = {}
  11. }
  12. if (typeof options === 'string') {
  13. options = {encoding: options}
  14. }
  15. options = options || {}
  16. var fs = options.fs || _fs
  17. var shouldThrow = true
  18. // DO NOT USE 'passParsingErrors' THE NAME WILL CHANGE!!!, use 'throws' instead
  19. if ('passParsingErrors' in options) {
  20. shouldThrow = options.passParsingErrors
  21. } else if ('throws' in options) {
  22. shouldThrow = options.throws
  23. }
  24. fs.readFile(file, options, function (err, data) {
  25. if (err) return callback(err)
  26. data = stripBom(data)
  27. var obj
  28. try {
  29. obj = JSON.parse(data, options ? options.reviver : null)
  30. } catch (err2) {
  31. if (shouldThrow) {
  32. err2.message = file + ': ' + err2.message
  33. return callback(err2)
  34. } else {
  35. return callback(null, null)
  36. }
  37. }
  38. callback(null, obj)
  39. })
  40. }
  41. function readFileSync (file, options) {
  42. options = options || {}
  43. if (typeof options === 'string') {
  44. options = {encoding: options}
  45. }
  46. var fs = options.fs || _fs
  47. var shouldThrow = true
  48. // DO NOT USE 'passParsingErrors' THE NAME WILL CHANGE!!!, use 'throws' instead
  49. if ('passParsingErrors' in options) {
  50. shouldThrow = options.passParsingErrors
  51. } else if ('throws' in options) {
  52. shouldThrow = options.throws
  53. }
  54. try {
  55. var content = fs.readFileSync(file, options)
  56. content = stripBom(content)
  57. return JSON.parse(content, options.reviver)
  58. } catch (err) {
  59. if (shouldThrow) {
  60. err.message = file + ': ' + err.message
  61. throw err
  62. } else {
  63. return null
  64. }
  65. }
  66. }
  67. function writeFile (file, obj, options, callback) {
  68. if (callback == null) {
  69. callback = options
  70. options = {}
  71. }
  72. options = options || {}
  73. var fs = options.fs || _fs
  74. var spaces = typeof options === 'object' && options !== null
  75. ? 'spaces' in options
  76. ? options.spaces : this.spaces
  77. : this.spaces
  78. var str = ''
  79. try {
  80. str = JSON.stringify(obj, options ? options.replacer : null, spaces) + '\n'
  81. } catch (err) {
  82. // Need to return whether a callback was passed or not
  83. if (callback) callback(err, null)
  84. return
  85. }
  86. fs.writeFile(file, str, options, callback)
  87. }
  88. function writeFileSync (file, obj, options) {
  89. options = options || {}
  90. var fs = options.fs || _fs
  91. var spaces = typeof options === 'object' && options !== null
  92. ? 'spaces' in options
  93. ? options.spaces : this.spaces
  94. : this.spaces
  95. var str = JSON.stringify(obj, options.replacer, spaces) + '\n'
  96. // not sure if fs.writeFileSync returns anything, but just in case
  97. return fs.writeFileSync(file, str, options)
  98. }
  99. function stripBom (content) {
  100. // we do this because JSON.parse would convert it to a utf8 string if encoding wasn't specified
  101. if (Buffer.isBuffer(content)) content = content.toString('utf8')
  102. content = content.replace(/^\uFEFF/, '')
  103. return content
  104. }
  105. var jsonfile = {
  106. spaces: null,
  107. readFile: readFile,
  108. readFileSync: readFileSync,
  109. writeFile: writeFile,
  110. writeFileSync: writeFileSync
  111. }
  112. module.exports = jsonfile