I have an array of conversation between two entities, each distinguished based on parent and level. Every request will be followed by a response object. The sample input structure is like below
[
{ "message": "one", "messageSequence": 0, "level": 1, "Parent": "", "messageType": "request" },
{ "message": "two", "messageType": "response", "messageSequence": 1 },
{ "message": "three-1 (3.1)", "messageSequence": 2, "level": 2, "Parent": 1, "messageType": "request" },
{ "message": "four", "messageType": "response", "messageSequence": 3 },
{ "message": "five-1 (5.1)", "messageSequence": 4, "level": 3, "Parent": 2, "messageType": "request" },
{ "message": "six", "messageType": "response", "messageSequence": 5 },
{ "message": "five-2 (5.2)", "messageSequence": 6, "level": 3, "Parent": 2, "messageType": "request" },
{ "message": "seven", "messageType": "response", "messageSequence": 7 },
{ "message": "three-2 (3.2)", "messageSequence": 8, "level": 2, "Parent": 1, "messageType": "request" },
{ "message": "eight", "messageType": "response", "messageSequence": 9 },
{ "message": "nine-1 (9.1)", "messageSequence": 10, "level": 3, "Parent": 2, "messageType": "request" },
{ "message": "ten", "messageType": "response", "messageSequence": 11 },
{ "message": "nine-2 (9.2) ", "messageSequence": 12, "level": 3, "Parent": 2, "messageType": "request" },
{ "message": "eleven", "messageType": "response", "messageSequence": 13 }
]
I am trying to generate a json based on request and its corresponding response. Below is the method which I am using to achieve it
var prevLevel;
var lastUserItem = 0;
function convertToJson(array) {
var map = {};
for (var i = 0; i < array.length; i++) {
var obj = array[i];
if (array[i].messageType == "request")
obj.request = [];
else
obj.response = {};
if (obj.level) {
prevLevel = obj.level
map[obj.level] = obj;
var parent = obj.Parent || '-';
if (!map[parent]) {
map[parent] = {
request: []
};
}
delete obj.Parent;
delete obj.level;
delete obj.messageType;
delete obj.messageSequence;
map[parent].request.push(obj);
lastUserItem = map[parent].request.length - 1;
} else {
delete obj.Parent;
delete obj.level;
delete obj.messageType;
delete obj.messageSequence;
if (map[prevLevel].request && map[prevLevel].request.length > 0) {
map[prevLevel].request[lastUserItem].response = {};
map[prevLevel].request[lastUserItem].response = obj;
} else {
map[prevLevel].response = {};
map[prevLevel].response = obj;
}
}
}
return map['-'].request;
}
var r = convertToJson(messages);
console.log(JSON.stringify(r));
The response which I am getting is not structured based on the request entity. Response from the above method
[
{
"message": "one",
"request": [
{
"message": "three-1 (3.1)",
"request": [
{
"message": "five-1 (5.1)",
"request": [],
"response":
{
"message": "six",
"response":
{}
}
},
{
"message": "five-2 (5.2)",
"request": [],
"response":
{
"message": "seven",
"response":
{}
}
}],
"response":
{
"message": "four",
"response":
{}
}
},
{
"message": "three-2 (3.2)",
"request": [
{
"message": "nine-1 (9.1)",
"request": [],
"response":
{
"message": "ten",
"response":
{}
}
},
{
"message": "nine-2 (9.2) ",
"request": [],
"response":
{
"message": "eleven",
"response":
{}
}
}],
"response":
{
"message": "eight",
"response":
{}
}
}],
"response":
{
"message": "two",
"response":
{}
}
}]
The Response objects are getting seperated. The expected json output is like below
{
"request": [{
"message": "one",
"response": {
"message": "two"
"request": [{
"message": "three-1 (3.1)",
"response": {
"message": "four"
"request": [{
"message": "five-1 (5.1)",
"response": {
"message": "six"
}
},
{
"message": "five-2 (5.2)",
"response": {
"message": "seven"
}
}
]
}
},
{
"message": "three-2 (3.2)",
"response": {
"message": "eight",
"request": [{
"message": "nine-1 (9.1)",
"response": {
"message": "ten"
}
},
{
"message": "nine-2 (9.2) ",
"response": {
"message": "eleven"
}
}
]
}
}
]
}
}]
}
Please suggest where I am going wrong. Anything to change in the input structure to get the desired output.
https://jsfiddle.net/49qLhL8g/4/
If the 'response' type is always directly coming after 'request', then you could build a new object with a look ahead to the next object and insert this message into the new object as result.
This proposal uses an array for the level reference and updates the levels in that array and as well as in the result.
var data = [{ message: "one", messageSequence: 0, level: 1, Parent: "", messageType: "request" }, { message: "two", messageType: "response", messageSequence: 1 }, { message: "three-1 (3.1)", messageSequence: 2, level: 2, Parent: 1, messageType: "request" }, { message: "four", messageType: "response", messageSequence: 3 }, { message: "five-1 (5.1)", messageSequence: 4, level: 3, Parent: 2, messageType: "request" }, { message: "six", messageType: "response", messageSequence: 5 }, { message: "five-2 (5.2)", messageSequence: 6, level: 3, Parent: 2, messageType: "request" }, { message: "seven", messageType: "response", messageSequence: 7 }, { message: "three-2 (3.2)", messageSequence: 8, level: 2, Parent: 1, messageType: "request" }, { message: "eight", messageType: "response", messageSequence: 9 }, { message: "nine-1 (9.1)", messageSequence: 10, level: 3, Parent: 2, messageType: "request" }, { message: "ten", messageType: "response", messageSequence: 11 }, { message: "nine-2 (9.2) ", messageSequence: 12, level: 3, Parent: 2, messageType: "request" }, { message: "eleven", messageType: "response", messageSequence: 13 }],
result = [],
levels = [result];
data.forEach(function (o, i, a) {
var level = o.level - 1, temp;
if (o.messageType !== 'request') {
return;
}
temp = { message: o.message, response: { message: a[i + 1].message, request: [] } };
levels[level + 1] = temp.response.request;
levels[level].push(temp);
});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I tried to do it using lodash in a very complex way as below .
var _lodash = require('lodash');
var arrayTwo = [
{ "message": "one", "messageSequence": 0, "level": 1, "Parent": "", "messageType": "request" },
{ "message": "two", "messageType": "response", "messageSequence": 1, "Parent": 0 },
{ "message": "three-1 (3.1)", "messageSequence": 2, "level": 2, "Parent": 1, "messageType": "request" },
{ "message": "four", "messageType": "response", "messageSequence": 3, "Parent": 2 },
{ "message": "five-1 (5.1)", "messageSequence": 4, "level": 3, "Parent": 2, "messageType": "request" },
{ "message": "six", "messageType": "response", "messageSequence": 5, "Parent": 3 },
{ "message": "five-2 (5.2)", "messageSequence": 6, "level": 3, "Parent": 2, "messageType": "request" },
{ "message": "seven", "messageType": "response", "messageSequence": 7, "Parent": 3 },
{ "message": "seven-1 (7.1)", "messageSequence": 8, "level": 4, "Parent": 3, "messageType": "request" },
{ "message": "seven-2 (7.2)", "messageType": "response", "messageSequence": 9, "Parent": 4 },
{ "message": "three-2 (3.2)", "messageSequence": 10, "level": 2, "Parent": 1, "messageType": "request" },
{ "message": "eight", "messageType": "response", "messageSequence": 11, "Parent": 2 },
{ "message": "nine-1 (9.1)", "messageSequence": 12, "level": 3, "Parent": 2, "messageType": "request" },
{ "message": "ten", "messageType": "response", "messageSequence": 13, "Parent": 3 },
{ "message": "nine-2 (9.2) ", "messageSequence": 14, "level": 3, "Parent": 2, "messageType": "request" },
{ "message": "eleven", "messageType": "response", "messageSequence": 15, "Parent": 3 }
];
var finalObj = {};
for (var i = 0; i < arrayTwo.length; i++) {
if (arrayTwo[i].messageType == "request") {
findAndAppendToRequest(arrayTwo[i]);
} else {
findAndAppendToResponse(arrayTwo[i]);
}
}
console.log(JSON.stringify(finalObj));
function findAndAppendToResponse(item) {
var parent = item.Parent;
var res = findBotNode();
var dt = _lodash.get(finalObj, res);
if (dt) {
if (!_lodash.has(finalObj, res + ".response")) {
_lodash.set(finalObj, res + ".response", {});
}
var data = {};
data.message = item.message;
_lodash.set(finalObj, res + ".response", data);
}
function findBotNode() {
var t = "";
if (parent == 0) {
t = 'request[' + 0 + ']';
} else {
for (var i = 0; i < parent; i++) {
if (!t) {
t = 'request[' + i + ']';
} else {
var temp = t + '.response.request[' + i + ']';
var cnt = 1;
while (!checkIfExists(temp)) {
temp = "";
var val = i - cnt;
temp = t + '.response.request[' + val + ']';
cnt++;
}
t = temp;
}
}
}
return t;
}
}
function checkIfExists(val) {
return _lodash.get(finalObj, val);
}
function findAndAppendToRequest(item) {
var msg = {};
msg.message = item.message;
if (!finalObj.request) {
finalObj.request = [];
finalObj.request.push(msg);
} else {
var parent = item.Parent;
var res = traverseNode();
var dt = _lodash.get(finalObj, res);
if (dt) {
if (!_lodash.has(finalObj, res + ".request")) {
_lodash.set(finalObj, res + ".request", []);
}
var ob = _lodash.get(finalObj, res + ".request");
ob.push(msg);
_lodash.set(finalObj, res + ".request", ob);
}
function traverseNode() {
var t = "";
for (var i = 0; i < parent; i++) {
if (!t) {
t = 'request[' + i + '].response';
} else {
var temp = t + '.request[' + i + '].response';
var cnt = 1;
while (!checkIfExists(temp)) {
temp = "";
var val = i - cnt;
temp = t + '.request[' + val + '].response';
cnt++;
}
t = temp;
}
}
return t;
}
}
}
Not sure if it work for all scenerios . @Nina Scholz great answer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With