org.python.modules._json.Encoder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jython-slim Show documentation
Show all versions of jython-slim Show documentation
Jython is an implementation of the high-level, dynamic, object-oriented
language Python written in 100% Pure Java, and seamlessly integrated with
the Java platform. It thus allows you to run Python on any Java platform.
package org.python.modules._json;
import org.python.core.AbstractDict;
import org.python.core.ArgParser;
import org.python.core.Py;
import org.python.core.PyFloat;
import org.python.core.PyInteger;
import org.python.core.PyLong;
import org.python.core.PyNewWrapper;
import org.python.core.PyList;
import org.python.core.PyObject;
import org.python.core.PyString;
import org.python.core.PyTuple;
import org.python.core.PyType;
import org.python.core.PyUnicode;
import org.python.core.Traverseproc;
import org.python.core.Visitproc;
import org.python.expose.ExposedGet;
import org.python.expose.ExposedNew;
import org.python.expose.ExposedType;
@ExposedType(name = "_json.encoder", base = PyObject.class)
public class Encoder extends PyObject implements Traverseproc {
public static final PyType TYPE = PyType.fromClass(Encoder.class);
@ExposedGet
public final String __module__ = "_json";
final AbstractDict markers;
final PyObject defaultfn;
final PyObject encoder;
final PyObject indent;
final PyObject key_separator;
final PyObject item_separator;
final PyObject sort_keys;
final boolean skipkeys;
final boolean allow_nan;
public Encoder(PyObject[] args, String[] kwds) {
this(TYPE, args, kwds);
}
public Encoder(PyType subtype, PyObject[] args, String[] kwds) {
super(subtype);
ArgParser ap = new ArgParser("encoder", args, kwds,
new String[]{"markers", "default", "encoder", "indent",
"key_separator", "item_separator", "sort_keys", "skipkeys", "allow_nan"});
ap.noKeywords();
PyObject m = ap.getPyObject(0);
markers = m == Py.None ? null : (AbstractDict) m;
defaultfn = ap.getPyObject(1);
encoder = ap.getPyObject(2);
indent = ap.getPyObject(3);
key_separator = ap.getPyObject(4);
item_separator = ap.getPyObject(5);
sort_keys = ap.getPyObject(6);
skipkeys = ap.getPyObject(7).__nonzero__();
allow_nan = ap.getPyObject(8).__nonzero__();
}
@ExposedNew
static PyObject Encoder___new__(PyNewWrapper new_, boolean init, PyType subtype,
PyObject[] args, String[] keywords) {
if (subtype == TYPE) {
return new Encoder(args, keywords);
} else {
return new EncoderDerived(subtype, args, keywords);
}
}
public PyObject __call__(PyObject obj) {
return __call__(obj, Py.Zero);
}
public PyObject __call__(PyObject obj, PyObject indent_level) {
PyList rval = new PyList();
encode_obj(rval, obj, 0);
return rval;
}
private PyString encode_float(PyObject obj) {
/* Return the JSON representation of a PyFloat */
double i = obj.asDouble();
if (Double.isInfinite(i) || Double.isNaN(i)) {
if (!allow_nan) {
throw Py.ValueError("Out of range float values are not JSON compliant");
}
if (i == Double.POSITIVE_INFINITY) {
return new PyString("Infinity");
} else if (i == Double.NEGATIVE_INFINITY) {
return new PyString("-Infinity");
} else {
return new PyString("NaN");
}
}
/* Use a better float format here? */
return obj.__repr__();
}
private PyString encode_string(PyObject obj) {
/* Return the JSON representation of a string */
return (PyString) encoder.__call__(obj);
}
private PyObject checkCircularReference(PyObject obj) {
PyObject ident = null;
if (markers != null) {
ident = Py.newInteger(Py.id(obj));
if (markers.__contains__(ident)) {
throw Py.ValueError("Circular reference detected");
}
markers.__setitem__(ident, obj);
}
return ident;
}
private void encode_obj(PyList rval, PyObject obj, int indent_level) {
/* Encode Python object obj to a JSON term, rval is a PyList */
if (obj == Py.None) {
rval.append(new PyString("null"));
} else if (obj == Py.True) {
rval.append(new PyString("true"));
} else if (obj == Py.False) {
rval.append(new PyString("false"));
} else if (obj instanceof PyString) {
rval.append(encode_string(obj));
} else if (obj instanceof PyInteger || obj instanceof PyLong) {
rval.append(obj.__str__());
} else if (obj instanceof PyFloat) {
rval.append(encode_float(obj));
} else if (obj instanceof PyList || obj instanceof PyTuple) {
encode_list(rval, obj, indent_level);
} else if (obj instanceof AbstractDict) {
/* Using AbstractDict instead of PyDictionary fixes http://bugs.jython.org/issue2622 */
encode_dict(rval, (AbstractDict) obj, indent_level);
} else {
PyObject ident = checkCircularReference(obj);
if (defaultfn == Py.None) {
throw Py.TypeError(String.format(".80s is not JSON serializable", obj.__repr__()));
}
PyObject newobj = defaultfn.__call__(obj);
encode_obj(rval, newobj, indent_level);
if (ident != null) {
markers.__delitem__(ident);
}
}
}
private void encode_dict(PyList rval, AbstractDict dct, int indent_level) {
/* Encode Python dict dct a JSON term */
if (dct.__len__() == 0) {
rval.append(new PyString("{}"));
return;
}
PyObject ident = checkCircularReference(dct);
rval.append(new PyString("{"));
/* TODO: C speedup not implemented for sort_keys */
int idx = 0;
for (PyObject key : dct.asIterable()) {
PyString kstr;
if (key instanceof PyString || key instanceof PyUnicode) {
kstr = (PyString) key;
} else if (key instanceof PyFloat) {
kstr = encode_float(key);
} else if (key instanceof PyInteger || key instanceof PyLong) {
kstr = key.__str__();
} else if (key == Py.True) {
kstr = new PyString("true");
} else if (key == Py.False) {
kstr = new PyString("false");
} else if (key == Py.None) {
kstr = new PyString("null");
} else if (skipkeys) {
continue;
} else {
throw Py.TypeError(String.format("keys must be a string: %.80s", key.__repr__()));
}
if (idx > 0) {
rval.append(item_separator);
}
PyObject value = dct.__getitem__(key);
PyString encoded = encode_string(kstr);
rval.append(encoded);
rval.append(key_separator);
encode_obj(rval, value, indent_level);
idx += 1;
}
if (ident != null) {
markers.__delitem__(ident);
}
rval.append(new PyString("}"));
}
private void encode_list(PyList rval, PyObject seq, int indent_level) {
PyObject ident = checkCircularReference(seq);
rval.append(new PyString("["));
int i = 0;
for (PyObject obj : seq.asIterable()) {
if (i > 0) {
rval.append(item_separator);
}
encode_obj(rval, obj, indent_level);
i++;
}
if (ident != null) {
markers.__delitem__(ident);
}
rval.append(new PyString("]"));
}
/* Traverseproc implementation */
@Override
public int traverse(Visitproc visit, Object arg) {
int retVal;
if (markers != null) {
retVal = visit.visit(markers, arg);
if (retVal != 0) {
return retVal;
}
}
if (defaultfn != null) {
retVal = visit.visit(defaultfn, arg);
if (retVal != 0) {
return retVal;
}
}
if (encoder != null) {
retVal = visit.visit(encoder, arg);
if (retVal != 0) {
return retVal;
}
}
if (indent != null) {
retVal = visit.visit(indent, arg);
if (retVal != 0) {
return retVal;
}
}
if (key_separator != null) {
retVal = visit.visit(key_separator, arg);
if (retVal != 0) {
return retVal;
}
}
if (item_separator != null) {
retVal = visit.visit(item_separator, arg);
if (retVal != 0) {
return retVal;
}
}
return sort_keys != null ? visit.visit(sort_keys, arg) : 0;
}
@Override
public boolean refersDirectlyTo(PyObject ob) {
return ob != null && (ob == markers || ob == defaultfn
|| ob == encoder || ob == indent || ob == key_separator
|| ob == item_separator || ob == sort_keys);
}
}