Skip to content

Commit d949063

Browse files
committed
next update.
1 parent 7410895 commit d949063

15 files changed

Lines changed: 6108 additions & 3479 deletions

.eslint.config.js

Lines changed: 0 additions & 72 deletions
This file was deleted.

README.md

Lines changed: 65 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
1-
jsonpickleJS
2-
============
1+
# jsonpickleJS
32

43
Javascript reinterpretation of Python jsonpickle to allow reading and (to a lesser extent)
54
writing JSON objects
65

76
Copyright © 2014-25 Michael Scott Asato Cuthbert.
87
Released under the BSD (3-clause) license. See LICENSE.
98

10-
Python to Javascript and Back
11-
==============================
9+
# Pre-class-based system
10+
11+
Note for 2025+: This system depends on legacy style functions that behave like objects.
12+
To use with modern Javascript you will need to assign all classes to globalThis (window, global).
13+
14+
# Python to Javascript and Back
1215
Python has a remarkable number of ways (for a language that believes there's only one way to do it)
1316
to transfer data between itself and Javascript, most obviously with the
1417
``json.dump()``/``json.dumps()`` calls, which work well on specifically created data, especially
@@ -39,14 +42,13 @@ It may be possible in the future to use ``instanceof``
3942
through the entire Global namespace to figure out what something is, but that seems rather dangerous
4043
and inefficient (A project for later).
4144

42-
Limitations
43-
===========
45+
# Limitations
4446
Remember that Javascript does not have tuples, so all tuple objects are changed to lists.
47+
4548
Namedtuples behave the same way, I believe. Dicts and Objects are identical in Javascript (both
4649
a blessing and a curse).
4750

48-
Security
49-
========
51+
# Security
5052
Pickle, jsonpickle, and jsonpickleJS all raise important security considerations you must be
5153
aware of. You will be loading data directly into Python or Javascript with no checks on what the
5254
data contains. Only load data you have personally produced if you want to be safe. In Javascript,
@@ -60,21 +62,61 @@ data, but anyone with JS programming experience can inject other data into your
6062
Be safe: be cautious going from Python to Javascript and NEVER accept Javascript-produced
6163
jsonpickle data from the net into your Python program in any sort of open environment.
6264

63-
Usage
64-
=====
65-
See the source code of: testUnpickle.html to see how to use it. JsonpickleJS follows the AMD
66-
moduleloader standard, so set the ``src=""`` attribute in the ``<script>`` to an AMD loader
67-
such as ``//cdnjs.cloudflare.com/ajax/libs/require.js/2.1.14/require.min.js``
68-
(or the included local version in ``jsonpickleJS/ext/require/require.js``) and
69-
the ``data-main`` attribute to ``jsonpickleJS/main`` (no ``.js``). Then call
70-
``var o = jsonpickle.decode(jsonStr)`` to get the Python object back as a JS object named ``o``.
71-
72-
See the cuthbertLab/music21 and cuthbertLab/music21j projects and especially the ``.show('vexflow')``
73-
component for an example of how jsonpickleJS can be extremely useful for projects that have
74-
parallel data structures between Python and Javascript.
75-
76-
Building
77-
========
65+
# Usage
66+
67+
You can use `jsonpickleJS` in modern JavaScript environments with either
68+
ES Modules or traditional `<script>` tags.
69+
70+
---
71+
72+
### ES Module (Modern usage)
73+
74+
```js
75+
// be sure jsonpickle is in your package.json and installed.
76+
77+
// # in python:
78+
// import jsonpickle
79+
// jsonStr = jsonpickle.encode(my_object)
80+
81+
import jsonpickle from 'jsonpickle';
82+
83+
const obj = jsonpickle.decode(jsonStr);
84+
// `obj` is now a JavaScript version of the original Python object
85+
// with proper classes.
86+
```
87+
88+
---
89+
90+
### `<script>` Tag (Legacy/global usage)
91+
92+
```html
93+
<script src="build/jsonpickle.min.js"></script>
94+
<script>
95+
const obj = jsonpickle.decode(jsonStr);
96+
console.log(obj);
97+
</script>
98+
```
99+
100+
This works without any build system. The `jsonpickle` global will be available automatically.
101+
102+
103+
### Example
104+
105+
You can find a working example in [`testUnpickle.html`](./testUnpickle.html).
106+
107+
108+
### Background
109+
110+
`jsonpickleJS` allows you to **decode Python-style JSON strings** into rich JavaScript objects.
111+
It’s especially useful for projects that mirror data structures across Python and JavaScript.
112+
113+
One real-world use case:
114+
Older versions of [`music21`](https://github.com/cuthbertLab/music21) and
115+
[`music21j`](https://github.com/cuthbertLab/music21j) use `jsonpickleJS` to render complex
116+
musical objects in the browser — such as using `.show('vexflow')` in music21 to visualize
117+
music sent from Python into JavaScript.
118+
119+
# Building
78120
Run once:
79121
```
80122
% npm install

build/jsonpickle.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

build/jsonpickle.min.js.LICENSE.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*!
22
*
3-
* jsonpickle.js 1.1.2 built on 2025-08-06
4-
* Copyright (c) 2013-2019 Michael Scott Cuthbert and cuthbertLab. BSD License
3+
* jsonpickle.js 1.2.0 built on 2025-08-06
4+
* Copyright (c) 2013–2025 Michael Scott Asato Cuthbert. BSD License
55
*
66
* http://github.com/cuthbertLab/jsonpickleJS
77
*

build/jsonpickle.min.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

eslint.config.js

Lines changed: 70 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,83 @@
1+
import globals from 'globals';
12
import { configs } from 'eslint-config-airbnb-extended/legacy';
23

34
export default [
45
...configs.base.recommended,
56
{
6-
"env": {
7-
"browser": true
7+
ignores: ['build/*', 'node_modules/*'],
8+
languageOptions: {
9+
ecmaVersion: 'latest',
10+
sourceType: 'module',
11+
globals: {
12+
...globals.browser,
13+
},
814
},
9-
"rules": {
10-
"array-bracket-spacing": ["off"],
11-
"arrow-parens": ["off"],
12-
"brace-style": ["off"],
13-
"camelcase": ["off"],
14-
"class-methods-use-this": ["off"],
15-
"comma-dangle": ["error", {
16-
"arrays": "only-multiline",
17-
"objects": "always-multiline",
18-
"imports": "always-multiline",
19-
"exports": "always-multiline",
20-
"functions": "ignore"
21-
}],
22-
"curly": ["error", "all"],
23-
"dot-location": ["error", "property"],
24-
"dot-notation": ["error"],
25-
"indent": ["error", 4],
26-
"import/extensions": ["off"],
27-
"import/prefer-default-export": ["off"],
28-
"import/no-named-as-default": ["off"],
29-
"import/no-named-as-default-member": ["off"],
30-
"import/no-unresolved": ["off"],
31-
"import/no-extraneous-dependencies": ["off"],
32-
"max-len": ["off"],
33-
"new-cap": ["off"],
34-
"no-case-declarations": ["error"],
35-
"no-console": ["off"],
36-
"no-continue": ["off"],
37-
"no-confusing-arrow": ["off"],
38-
"no-else-return": ["off"],
39-
"no-lonely-if": ["off"],
40-
"no-mixed-operators": ["off"],
41-
"no-multi-spaces": ["off"],
42-
"no-multiple-empty-lines": ["error", { "max": 3 }],
43-
"no-param-reassign": ["off"],
44-
"no-plusplus": ["error", { "allowForLoopAfterthoughts": true }],
45-
"no-restricted-syntax": [
15+
rules: {
16+
'array-bracket-spacing': ['off'],
17+
'arrow-parens': ['off'],
18+
'brace-style': ['off'],
19+
'camelcase': ['off'],
20+
'class-methods-use-this': ['off'],
21+
'comma-dangle': ['error', {
22+
'arrays': 'only-multiline',
23+
'objects': 'always-multiline',
24+
'imports': 'always-multiline',
25+
'exports': 'always-multiline',
26+
'functions': 'ignore',
27+
}],
28+
'curly': ['error', 'all'],
29+
'dot-location': ['error', 'property'],
30+
'dot-notation': ['error'],
31+
'indent': ['error', 4],
32+
'import/extensions': ['off'],
33+
'import/prefer-default-export': ['off'],
34+
'import/no-named-as-default': ['off'],
35+
'import/no-named-as-default-member': ['off'],
36+
'import/no-unresolved': ['off'],
37+
'import/no-extraneous-dependencies': ['off'],
38+
'max-len': ['off'],
39+
'new-cap': ['off'],
40+
'no-case-declarations': ['error'],
41+
'no-console': ['off'],
42+
'no-continue': ['off'],
43+
'no-confusing-arrow': ['off'],
44+
'no-else-return': ['off'],
45+
'no-lonely-if': ['off'],
46+
'no-mixed-operators': ['off'],
47+
'no-multi-spaces': ['off'],
48+
'no-multiple-empty-lines': ['error', { 'max': 3 }],
49+
'no-param-reassign': ['off'],
50+
'no-plusplus': ['error', { 'allowForLoopAfterthoughts': true }],
51+
'no-restricted-syntax': [
4652
2,
47-
"DebuggerStatement",
48-
"LabeledStatement",
49-
"WithStatement"
53+
'DebuggerStatement',
54+
'LabeledStatement',
55+
'WithStatement'
5056
],
51-
"no-shadow": ["off"],
52-
"no-trailing-spaces": ["off"],
53-
"no-use-before-define": ["off"],
54-
"no-underscore-dangle": ["off"],
55-
"no-unused-vars": [
56-
"error",
57+
'no-shadow': ['off'],
58+
'no-trailing-spaces': ['off'],
59+
'no-use-before-define': ['off'],
60+
'no-underscore-dangle': ['off'],
61+
'no-unused-vars': [
62+
'error',
5763
{
58-
"args": "none",
59-
"varsIgnorePattern": "^i$|^j$|^unused|^junk|^counter"
64+
args: 'none',
65+
caughtErrors: 'none',
66+
varsIgnorePattern: '^i$|^j$|^unused|^junk|^counter|^_',
6067
}
6168
],
62-
"object-curly-spacing": ["off"],
63-
"object-property-newline": ["off"],
64-
"operator-linebreak": ["error", "before"],
65-
"padded-blocks": ["off"],
66-
"prefer-template": ["off"],
67-
"quote-props": ["off"],
68-
"radix": ["off"],
69-
"space-infix-ops": ["off"],
70-
"spaced-comment": ["off"],
71-
"strict": ["error", "global"],
72-
"yoda": ["error", "never", { "exceptRange": true }]
73-
}
69+
'object-curly-spacing': ['off'],
70+
'object-property-newline': ['off'],
71+
'operator-linebreak': ['error', 'before'],
72+
'padded-blocks': ['off'],
73+
'prefer-destructuring': ['off'],
74+
'prefer-template': ['off'],
75+
'quote-props': ['off'],
76+
'radix': ['off'],
77+
'space-infix-ops': ['off'],
78+
'spaced-comment': ['off'],
79+
'strict': ['error', 'global'],
80+
'yoda': ['error', 'never', { 'exceptRange': true }],
81+
},
7482
},
7583
];

js/index.js

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,26 @@
22
* jsonpickleJS -- interpretation of python jsonpickle in Javascript
33
* index.js -- main loader -- this should be the only file that most users care about.
44
*
5-
* Copyright (c) 2014-19 Michael Scott Cuthbert and cuthbertLab
5+
* Copyright (c) 2014-25 Michael Scott Cuthbert and cuthbertLab
66
*/
7-
import 'regenerator-runtime/runtime';
8-
97
import * as unpickler from './unpickler.js';
108
import * as pickler from './pickler.js';
119
import * as util from './util.js';
1210
import { tags } from './tags.js';
1311
import { handlers } from './handlers.js';
1412

1513
// noinspection JSUnusedGlobalSymbols
16-
export { pickler, unpickler, util, tags, handlers };
14+
export {
15+
pickler, unpickler, util, tags, handlers,
16+
};
1717

1818
export function encode(
19-
value, unpicklable=true, make_refs=true,
20-
keys=false, max_depth, backend
19+
value,
20+
unpicklable=true,
21+
make_refs=true,
22+
keys=false,
23+
max_depth=undefined,
24+
backend=undefined,
2125
) {
2226
const options = {
2327
unpicklable,

0 commit comments

Comments
 (0)