JSON / MARC encoding
authorAdam Dickmeiss <adam@indexdata.dk>
Thu, 5 Dec 2013 15:40:55 +0000 (16:40 +0100)
committerAdam Dickmeiss <adam@indexdata.dk>
Thu, 5 Dec 2013 15:40:55 +0000 (16:40 +0100)
include/yaz/json.h
include/yaz/marcdisp.h
src/json.c
src/marcdisp.c

index aab0159..d3974ae 100644 (file)
@@ -201,6 +201,14 @@ void json_write_wrbuf_pretty(struct json_node *node, WRBUF result);
 YAZ_EXPORT
 void wrbuf_json_puts(WRBUF b, const char *str);
 
+/** \brief writes JSON text to WRBUF with escaping
+    \param b result
+    \param cp char buffer
+    \param sz size of char buffer
+*/
+YAZ_EXPORT
+void wrbuf_json_write(WRBUF b, const char *cp, size_t sz);
+
 YAZ_END_CDECL
 
 #endif
index f1eaae8..0b2b66b 100644 (file)
@@ -76,6 +76,8 @@ YAZ_EXPORT void yaz_marc_xml(yaz_marc_t mt, int xmlmode);
 #define YAZ_MARC_CHECK     6
 /** \brief Output format: Turbo MARC Index Data format (XML based) */
 #define YAZ_MARC_TURBOMARC 7
+/** \brief Output format: JSON */
+#define YAZ_MARC_JSON      8
 
 /** \brief set iconv handle for character set conversion */
 YAZ_EXPORT void yaz_marc_iconv(yaz_marc_t mt, yaz_iconv_t cd);
index 1933b8a..2364e43 100644 (file)
@@ -462,7 +462,7 @@ struct json_node *json_parse(const char *json_str, const char **errmsg)
     return json_parse2(json_str, errmsg, 0);
 }
 
-static void wrbuf_json_write(WRBUF b, const char *cp, size_t sz)
+void wrbuf_json_write(WRBUF b, const char *cp, size_t sz)
 {
     size_t i;
     for (i = 0; i < sz; i++)
index ad9eed6..78244a0 100644 (file)
@@ -632,6 +632,8 @@ int yaz_marc_write_mode(yaz_marc_t mt, WRBUF wr)
         return yaz_marc_write_iso2709(mt, wr);
     case YAZ_MARC_CHECK:
         return yaz_marc_write_check(mt, wr);
+    case YAZ_MARC_JSON:
+        return yaz_marc_write_json(mt, wr);
     }
     return -1;
 }
@@ -1238,6 +1240,87 @@ int yaz_marc_write_iso2709(yaz_marc_t mt, WRBUF wr)
     return 0;
 }
 
+int yaz_marc_write_json(yaz_marc_t mt, WRBUF w)
+{
+    int identifier_length;
+    struct yaz_marc_node *n;
+    const char *leader = 0;
+    int first = 1;
+
+    wrbuf_puts(w, "{\n");
+    for (n = mt->nodes; n; n = n->next)
+        if (n->which == YAZ_MARC_LEADER)
+            leader = n->u.leader;
+
+    if (!leader)
+        return -1;
+
+    if (!atoi_n_check(leader+11, 1, &identifier_length))
+        return -1;
+
+    wrbuf_puts(w, "\t\"leader\":\"");
+    wrbuf_json_puts(w, leader);
+    wrbuf_puts(w, "\",\n");
+    wrbuf_puts(w, "\t\"fields\":\n\t[\n");
+
+    for (n = mt->nodes; n; n = n->next)
+    {
+        struct yaz_marc_subfield *s;
+        int i;
+        const char *sep = "";
+        switch (n->which)
+        {
+        case YAZ_MARC_CONTROLFIELD:
+            if (first)
+                first = 0;
+            else
+                wrbuf_puts(w, ",\n");
+            wrbuf_puts(w, "\t\t{\n\t\t\t\"");
+            wrbuf_json_puts(w, n->u.controlfield.tag);
+            wrbuf_puts(w, "\":\"");
+            wrbuf_json_puts(w, n->u.controlfield.data);
+            wrbuf_puts(w, "\"\n\t\t}");
+            break;
+        case YAZ_MARC_DATAFIELD:
+            if (first)
+                first = 0;
+            else
+                wrbuf_puts(w, ",\n");
+
+            wrbuf_puts(w, "\t\t{\n\t\t\t\"");
+            wrbuf_json_puts(w, n->u.datafield.tag);
+            wrbuf_puts(w, "\":\n\t\t\t{\n\t\t\t\t\"subfields\":\n\t\t\t\t[\n");
+            for (s = n->u.datafield.subfields; s; s = s->next)
+            {
+                size_t using_code_len = get_subfield_len(mt, s->code_data,
+                                                         identifier_length);
+                wrbuf_puts(w, sep);
+                sep = ",\n";
+                wrbuf_puts(w, "\t\t\t\t\t{\n\t\t\t\t\t\t\"");
+                wrbuf_json_write(w, s->code_data, using_code_len);
+                wrbuf_puts(w, "\":\"");
+                wrbuf_json_puts(w, s->code_data + using_code_len);
+                wrbuf_puts(w, "\"\n\t\t\t\t\t}");
+            }
+            wrbuf_puts(w, "\n\t\t\t\t]");
+            if (n->u.datafield.indicator[0])
+            {
+                int i;
+                for (i = 0; n->u.datafield.indicator[i]; i++)
+                {
+                    wrbuf_puts(w, ",\n");
+                    wrbuf_printf(w, "\t\t\t\t\"ind%d\":\"%c\"", i + 1,
+                                 n->u.datafield.indicator[i]);
+                }
+            }
+            wrbuf_puts(w, "\n\t\t\t}\n");
+            wrbuf_puts(w, "\n\t\t}");
+            break;
+        }
+    }
+    wrbuf_puts(w, "\n\t]\n");
+    wrbuf_puts(w, "}\n");
+}
 
 int yaz_marc_decode_wrbuf(yaz_marc_t mt, const char *buf, int bsize, WRBUF wr)
 {
@@ -1368,6 +1451,8 @@ int yaz_marc_decode_formatstr(const char *arg)
         mode = YAZ_MARC_XCHANGE;
     if (!strcmp(arg, "line"))
         mode = YAZ_MARC_LINE;
+    if (!strcmp(arg, "json"))
+        mode = YAZ_MARC_JSON;
     return mode;
 }