Hi all,

Perhaps this is hidden somewhere in the rdflib repo and I wasn’t able to find 
it, but I found myself wanting to encode rdflib.term.Literal values to JSON as 
e.g. {“value”: literal.value, “datatype”: literal.datatype, …}. I ended up 
adapting the advice of a SO post. Here is my answer on SO with an rdflib 
example: 
[https://stackoverflow.com/a/69588931/1820042](https://stackoverflow.com/a/69588931/1820042)
 
<https://www.fastmail.com/mail/Inbox/compose/[https://stackoverflow.com/a/69588931/1820042](https://stackoverflow.com/a/69588931/1820042)>.

Also reproduced below. I hope folks find it useful. Also feel free to point out 
where this has already been done, and I’ll pip install that instead of my 
custom code!

`from json.encoder import (_make_iterencode, JSONEncoder,
                          encode_basestring_ascii, INFINITY,
                          encode_basestring)

class CustomObjectEncoder(JSONEncoder):

    def iterencode(self, o, _one_shot=False):
        """Encode the given object and yield each string
        representation as available.

        For example::

            for chunk in JSONEncoder().iterencode(bigobject):
                mysocket.write(chunk)

        Change from json.encoder.JSONEncoder.iterencode is setting
        _one_shot=False and isinstance=self.isinstance
        in call to `_make_iterencode`.
        And not using `c_make_encoder`.

        """
        if self.check_circular:
            markers = {}
        else:
            markers = None
        if self.ensure_ascii:
            _encoder = encode_basestring_ascii
        else:
            _encoder = encode_basestring

        def floatstr(o, allow_nan=self.allow_nan,
                _repr=float.__repr__, _inf=INFINITY, _neginf=-INFINITY):
            # Check for specials.  Note that this type of test is processor
            # and/or platform-specific, so do tests which don't depend on the
            # internals.

            if o != o:
                text = 'NaN'
            elif o == _inf:
                text = 'Infinity'
            elif o == _neginf:
                text = '-Infinity'
            else:
                return _repr(o)

            if not allow_nan:
                raise ValueError(
                    "Out of range float values are not JSON compliant: " +
                    repr(o))

            return text

        _iterencode = _make_iterencode(
                markers, self.default, _encoder, self.indent, floatstr,
                self.key_separator, self.item_separator, self.sort_keys,
                self.skipkeys, _one_shot=False, isinstance=self.isinstance)
        return _iterencode(o, 0)
` 
Example subclass:

`import datetime

from rdflib.term import Literal, BNode

class RDFTermEncoder(CustomObjectEncoder):
    def isinstance(self, o, cls):
        if isinstance(o, (Literal, BNode)):
            return False
        return isinstance(o, cls)
    def default(self, o):
        if isinstance(o, Literal):
            rv = {"value": o.value}
            if o.datatype is not None:
                rv["datatype"] = o.datatype
            if o.language is not None:
                rv["lang"] = o.language
            return rv
        if isinstance(o, BNode):
            return "http://localhost/bnode/"; + str(o)
        if isinstance(o, datetime.datetime):
            return o.isoformat()
        if isinstance(o, datetime.date):
            return str(o)
        # Let the base class default method raise the TypeError
        return super().default(o)
` 
I just used this successfully for my work as

`db_json = json.loads(json.dumps(db_custom, cls=RDFTermEncoder))
` 
Best,
Donny

—
Donny Winston, PhD (he/him/his) | Polyneme LLC
https://donnywinston.com | https://polyneme.xyz

If I’ve emailed you, I’d love to speak with you.
Schedule a meeting (15min+): https://meet.polyneme.xyz 

-- 
http://github.com/RDFLib
--- 
You received this message because you are subscribed to the Google Groups 
"rdflib-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to rdflib-dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/rdflib-dev/5a70d567-652c-45da-b500-7776447210dd%40www.fastmail.com.

Reply via email to