3

I am writing REST API to perform transformation using library like JSONata.

API receive a JSON that has data and map as given below. This is simple example.

{ 
   "map":{ 
      "name":"title",
      "info":"description",
      "data":{ 
         "text":"blog",
         "date":"date"
      }
   },
   "data":{ 
      "title":"title1",
      "description":"description1",
      "blog":"This is a blog.",
      "date":"11/4/2013"
   }
}

The Node.JS code is given below.

app.post('/JSONTransform', function (req, res, next) {
    const data = req.body.data;
    const map = req.body.map;
    var expression = jsonata(map);
    var result = expression.evaluate(data);
    res.send(result);
});

The map variable contain the following

{ 
      "name":"title",
      "info":"description",
      "data":{ 
         "text":"blog",
         "date":"date"
      }
}

JSONdata expects value to be JSON Path without quotes as below.

{ 
      "name":title,
      "info":description,
      "data":{ 
         "text":blog,
         "date":date
      }
}

Please suggest best option to remove the quotes only in all JSON Values.

I write function to remove the quotes in value by iterating the JSON object.

    function jsoniterate(map) {

        Object.keys(map).forEach(key => {
            console.log(map[key]);
            if (typeof (map[key]) == 'object') {
                arr1.push('"' + key + '": {');
                jsoniterate(map[key]);
                arr1.push('}');
            }
            else {
                arr1.push('"' + key + '":' + map[key]);
            }

        });
    }

but the complexity increase when the JSON value has object and so on . and also ',' should be placed between each set of key value pair.

I found some solution using regular expression but that target only for numeric value in the JSON Value. Here, it should be for all JSON values

JSONdata expects value to be JSON Path without quotes as below.

{ 
      "name":title,
      "info":description,
      "data":{ 
         "text":blog,
         "date":date
      }
}

user3497702
  • 695
  • 3
  • 12
  • 25
  • 1
    Not sure but this `{ "name":title, "info":description, "data":{ "text":blog, "date":date } }` seems to be wrong unless `title`,`description`.... are variable declared – brk Sep 09 '19 at 16:05
  • The title and description are JSON path in the data JSON. The data JSON is given below. "data":{ "title":"title1", "description":"description1", "blog":"This is a blog.", "date":"11/4/2013" } Please find the sample [here](http://try.jsonata.org/HJXxE9TEH) – user3497702 Sep 09 '19 at 16:09
  • Would tell it is useless - you can work with strings very similar as with key names, but in case - what if you set a prefix and suffix - some char or combination that should not be anywhere else and then replace them in stringified json ? – Jan Sep 10 '19 at 06:55
  • And some parser code can help too - there is often quite simple recursive stringify method. For example Gason C++ I translated to C#. Here https://github.com/eltomjan/Gason/blob/master/src/ValueWriter.cs method DumpValue prints json... – Jan Sep 10 '19 at 07:06

2 Answers2

4

Use JSON.stringify() to stringify types that your function shouldn't be worrying about, and leverage template strings with maps (they fix the comma problem for objects) to simplify the code:

function stringify(k, v) {
  if(typeof v == 'string') {
    return `"${k}": ${v}`;
  } else if(typeof v == 'object') {
    return `"${k}": {${Object.entries(v).map(([k, v]) => stringify(k, v))}}`;
  } else {
    return `"${k}": ${JSON.stringify(v)}`;
  }
}

stringify("map", map)
//outputs "map": {"name": title,"info": description,"data": {"text": blog,"date": date}}

That being said, I don't think this is the best way to solve this problem.

If you changed the format in which the API accepts the map, then converting it would be a breeze. For example:

const map = { 
  "'name'":"title",
  "'info'":"description",
  "'data'":{ 
      "'text'":"blog",
      "'date'":"date"
  }
};

JSON.stringify(map).replace(/"/g, "").replace(/\'/g, "\"");
//returns {"name":title,"info":description,"data":{"text":blog,"date":date}}

You could also just accept the map as a string in JSONata format.

Codebling
  • 10,764
  • 2
  • 38
  • 66
0

Thanks for all your response.

I pass entire map as a string.

The escape character appear inside the map for quotes and others by Newtosoft.


string db_model = System.IO.File.ReadAllText(@"..\Test.Just.Net.Core.3.0\App_Data\JSONATA\JSONTab\db_model_tab.json");
var api_param_db_model = JObject.Parse(db_model);
JObject api_param_object = new JObject();
api_param_object.Add("map", transform);
api_param_object.Add("data", api_param_db_model.SelectToken("$"));

Please find the data sample passed to node.js api.

{  
   "map":"{ \r\n\t\"name\":title,\r\n\t\"info\":description,\r\n\t\"data\":{ \r\n\t\t\"text\":blog,\r\n\t\t\"date\":date\r\n\t}\r\n}",
   "data":{  
      "title":"title1",
      "description":"description1",
      "blog":"This is a blog.",
      "date":"11/4/2013"
   }
}

with this data, I no need to do anything in the node.js.

user3497702
  • 695
  • 3
  • 12
  • 25