Permalink
Browse files

Initial version without array diffs

  • Loading branch information...
0 parents commit 2c0305c05650dd264e6538b29f61c507d98ade39 @andreyvit committed Apr 17, 2012
Showing with 168 additions and 0 deletions.
  1. +3 −0 .gitignore
  2. +2 −0 .npmignore
  3. +2 −0 bin/json-diff.js
  4. +34 −0 lib/cli.iced
  5. +68 −0 lib/index.iced
  6. +26 −0 package.json
  7. +32 −0 test/diff_test.coffee
  8. +1 −0 test/mocha.opts
@@ -0,0 +1,3 @@
+node_modules
+*.js
+!bin/*.js
@@ -0,0 +1,2 @@
+*.iced
+*.coffee
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('../lib/cli')(process.argv.slice(2));
@@ -0,0 +1,34 @@
+fs = require 'fs'
+
+{ diff } = require './index'
+
+
+module.exports = (argv) ->
+ options = require('dreamopt') [
+ "Usage: json-diff [-v] first.json second.json"
+
+ "Arguments:"
+ " first.json Old file #var(file1) #required"
+ " second.json New file #var(file2) #required"
+
+ "General options:"
+ " -v, --verbose Output progress info"
+ ], argv
+
+ console.log "Loading files..." if options.verbose
+ await
+ fs.readFile options.file1, 'utf8', defer(err1, data1)
+ fs.readFile options.file2, 'utf8', defer(err2, data2)
+
+ throw err1 if err1
+ throw err2 if err2
+
+ console.log "Parsing old file..." if options.verbose
+ json1 = JSON.parse(data1)
+ console.log "Parsing new file..." if options.verbose
+ json2 = JSON.parse(data2)
+
+ console.log "Running diff..." if options.verbose
+ result = diff(json1, json2)
+
+ process.stdout.write JSON.stringify(result)
@@ -0,0 +1,68 @@
+{ SequenceMatcher } = require 'difflib'
+
+
+extendedTypeOf = (obj) ->
+ result = typeof obj
+ if result is 'object' and obj.constructor is 'Array'
+ 'array'
+ else
+ result
+
+
+emptyDiffStats = ->
+ matchedKeys: 0
+ unmatchedKeys: 0
+
+
+objectDiff = (obj1, obj2, stats) ->
+ result = {}
+
+ keys1 = Object.keys(obj1)
+ keys2 = Object.keys(obj2)
+
+ for own key, value1 of obj1 when !(key of obj2)
+ result["#{key}__deleted"] = value1
+ stats.unmatchedKeys++ if stats
+
+ for own key, value2 of obj2 when !(key of obj1)
+ result["#{key}__added"] = value2
+ stats.unmatchedKeys++ if stats
+
+ for own key, value1 of obj1 when key of obj2
+ value2 = obj2[key]
+ if change = diff(value1, value2)
+ result[key] = change
+ stats.matchedKeys++ if stats
+ else
+ stats.matchedKeys++ if stats
+
+ if Object.keys(result).length is 0
+ return undefined
+
+ return result
+
+
+arrayDiff = (obj1, obj2, stats) ->
+ opcodes = new SequenceMatcher(null, "a", "ab").getOpcodes()
+ console.log opcodes
+ return
+
+
+diff = (obj1, obj2, stats) ->
+ type1 = extendedTypeOf obj1
+ type2 = extendedTypeOf obj2
+
+ if type1 == type2
+ switch type1
+ when 'object'
+ return objectDiff(obj1, obj2, stats)
+ when 'array'
+ return arrayDiff(obj1, obj2, stats)
+
+ if obj1 != obj2
+ { __old: obj1, __new: obj2 }
+ else
+ undefined
+
+
+module.exports = { diff }
@@ -0,0 +1,26 @@
+{
+ "author": "Andrey Tarantsov <andreyvit@me.com>",
+ "name": "json-diff",
+ "description": "JSON diff",
+ "version": "0.0.1",
+ "homepage": "https://github.com/andreyvit/json-diff",
+ "repository": {
+ "url": "git@github.com:andreyvit/json-diff.git"
+ },
+ "main": "lib/index.js",
+ "bin": "bin/json-diff.js",
+ "scripts": {
+ "test": "./node_modules/mocha/bin/mocha"
+ },
+ "dependencies": {
+ "dreamopt": "~0.6.0",
+ "difflib": "~0.2.1"
+ },
+ "devDependencies": {
+ "mocha": "~1.0.1"
+ },
+ "optionalDependencies": {},
+ "engines": {
+ "node": "*"
+ }
+}
@@ -0,0 +1,32 @@
+assert = require 'assert'
+
+{ diff } = require '../lib/index'
+
+describe 'diff', ->
+
+ it "should return undefined for two identical numbers", ->
+ assert.deepEqual undefined, diff(42, 42)
+
+ it "should return undefined for two identical strings", ->
+ assert.deepEqual undefined, diff("foo", "foo")
+
+ it "should return { __old: <old value>, __new: <new value> } object for two different numbers", ->
+ assert.deepEqual { __old: 42, __new: 10 }, diff(42, 10)
+
+ it "should return undefined for two objects with identical contents", ->
+ assert.deepEqual undefined, diff({ foo: 42, bar: 10 }, { foo: 42, bar: 10 })
+
+ it "should return undefined for two object hierarchies with identical contents", ->
+ assert.deepEqual undefined, diff({ foo: 42, bar: { bbbar: 10, bbboz: 11 } }, { foo: 42, bar: { bbbar: 10, bbboz: 11 } })
+
+ it "should return { <key>__deleted: <old value> } when the second object is missing a key", ->
+ assert.deepEqual { foo__deleted: 42 }, diff({ foo: 42, bar: 10 }, { bar: 10 })
+
+ it "should return { <key>__added: <new value> } when the first object is missing a key", ->
+ assert.deepEqual { foo__added: 42 }, diff({ bar: 10 }, { foo: 42, bar: 10 })
+
+ it "should return { <key>: { __old: <old value>, __new: <new value> } } for two objects with diffent scalar values for a key", ->
+ assert.deepEqual { foo: { __old: 42, __new: 10 } }, diff({ foo: 42 }, { foo: 10 })
+
+ it "should return { <key>: <diff> } with a recursive diff for two objects with diffent values for a key", ->
+ assert.deepEqual { bar: { bbboz__deleted: 11, bbbar: { __old: 10, __new: 12 } } }, diff({ foo: 42, bar: { bbbar: 10, bbboz: 11 }}, { foo: 42, bar: { bbbar: 12 }})
@@ -0,0 +1 @@
+--reporter spec

0 comments on commit 2c0305c

Please sign in to comment.