Function: json-insert

json-insert is a function defined in json.c.

Signature

(json-insert OBJECT &rest ARGS)

Documentation

Insert the JSON representation of OBJECT before point.

This is the same as (insert (json-serialize OBJECT)), but potentially faster. See the function json-serialize for allowed values of OBJECT.

Probably introduced at or before Emacs version 27.1.

Source Code

// Defined in /usr/src/emacs/src/json.c
{
  ptrdiff_t count = SPECPDL_INDEX ();

#ifdef WINDOWSNT
  if (!json_initialized)
    {
      Lisp_Object status;
      json_initialized = init_json_functions ();
      status = json_initialized ? Qt : Qnil;
      Vlibrary_cache = Fcons (Fcons (Qjson, status), Vlibrary_cache);
    }
  if (!json_initialized)
    Fsignal (Qjson_unavailable,
	     list1 (build_unibyte_string ("jansson library not found")));
#endif

  struct json_configuration conf =
    {json_object_hashtable, json_array_array, QCnull, QCfalse};
  json_parse_args (nargs - 1, args + 1, &conf, false);

  json_t *json = lisp_to_json (args[0], &conf);
  record_unwind_protect_ptr (json_release_object, json);

  prepare_to_modify_buffer (PT, PT, NULL);
  move_gap_both (PT, PT_BYTE);
  struct json_insert_data data;
  data.inserted_bytes = 0;
  /* Could have used json_dumpb, but that became available only in
     Jansson 2.10, whereas we want to support 2.7 and upward.  */
  int status = json_dump_callback (json, json_insert_callback, &data,
                                   JSON_COMPACT | JSON_ENCODE_ANY);
  if (status == -1)
    {
      if (CONSP (data.error))
        xsignal (XCAR (data.error), XCDR (data.error));
      else
        json_out_of_memory ();
    }

  ptrdiff_t inserted = 0;
  ptrdiff_t inserted_bytes = data.inserted_bytes;
  if (inserted_bytes > 0)
    {
      /* If required, decode the stuff we've read into the gap.  */
      struct coding_system coding;
      /* JSON strings are UTF-8 encoded strings.  If for some reason
	 the text returned by the Jansson library includes invalid
	 byte sequences, they will be represented by raw bytes in the
	 buffer text.  */
      setup_coding_system (Qutf_8_unix, &coding);
      coding.dst_multibyte =
	!NILP (BVAR (current_buffer, enable_multibyte_characters));
      if (CODING_MAY_REQUIRE_DECODING (&coding))
	{
          /* Now we have all the new bytes at the beginning of the gap,
             but `decode_coding_gap` needs them at the end of the gap, so
             we need to move them.  */
          memmove (GAP_END_ADDR - inserted_bytes, GPT_ADDR, inserted_bytes);
	  decode_coding_gap (&coding, inserted_bytes);
	  inserted = coding.produced_char;
	}
      else
	{
          /* Make the inserted text part of the buffer, as unibyte text.  */
          eassert (NILP (BVAR (current_buffer, enable_multibyte_characters)));
          insert_from_gap_1 (inserted_bytes, inserted_bytes, false);

	  /* The target buffer is unibyte, so we don't need to decode.  */
	  invalidate_buffer_caches (current_buffer,
				    PT, PT + inserted_bytes);
	  adjust_after_insert (PT, PT_BYTE,
			       PT + inserted_bytes,
			       PT_BYTE + inserted_bytes,
			       inserted_bytes);
	  inserted = inserted_bytes;
	}
    }

  /* Call after-change hooks.  */
  signal_after_change (PT, 0, inserted);
  if (inserted > 0)
    {
      update_compositions (PT, PT, CHECK_BORDER);
      /* Move point to after the inserted text.  */
      SET_PT_BOTH (PT + inserted, PT_BYTE + inserted_bytes);
    }

  return unbind_to (count, Qnil);
}