R - JSON Structure for POST - r

I've read everything i can find around create JSONs using toJSON(), but it's just not clicking. Any guidance would be greatly appreciated.
I am trying to create a JSON for a POST request to an API. I'm trying to create the following structure:
{
"configuration": {
"Id": 1,
"OptionIds": [
261,
263,
533122,
228
]
},
"length": 15000,
"zip": "92691",
"Date": "2019-09-11T15:46:31.354Z"
}
Trying to break it down element by element I can begin to get close, but can never get to the final solution once attempt to combine everything.
For example.
v_opt_ids <- list(OptionsIds = c(261,
263,
533122,
228))
cat(jsonlite::toJSON(v_opt_ids, pretty=T))
Produces:
{
"OptionsIds": [261, 263, 533122, 228]
}
And while this is not exactly what i'm aiming for in that portion, when combined with additional elements.
config <- data.frame(
vehicleId = c(444449),
v_opt_ids)
cat(jsonlite::toJSON(list(configuration = config), pretty=T))
Things go awry pretty quickly..
{
"configuration": [
{
"vehicleId": 444449,
"OptionsIds": 261
},
{
"vehicleId": 444449,
"OptionsIds": 263
},
{
"vehicleId": 444449,
"OptionsIds": 533122
},
{
"vehicleId": 444449,
"OptionsIds": 228
}
]
}
Any guidance would be greatly appreciated.

Use nested lists:
L <- list(
configuration = list(
Id = 1,
OptionIds = c(261, 263, 533122, 228)
),
length = 15000,
zip = "92691",
Date = "2019-09-11T15:46:31.354Z"
)
jsonlite::toJSON(L, pretty = TRUE, auto_unbox = TRUE)
# {
# "configuration": {
# "Id": 1,
# "OptionIds": [261, 263, 533122, 228]
# },
# "length": 15000,
# "zip": "92691",
# "Date": "2019-09-11T15:46:31.354Z"
# }
(pretty=TRUE is not required for the JSON, just using it to attempt to match your expected output. auto_unbox=TRUE ensures that one gets "Id":1 instead of "Id":[1], which is functionally identical for most things that consume json, some find it a preferable format.

Related

Dynamically Parse Child Nodes in JSON

I have a deserialized object that I want to dynamically loop through to return the related results. The response package looks like so:
{"RatingResponse":
{"Success":"true",
"Message":"",
"QuoteID":"57451",
"LoadNum":"57451",
"Rates":
{"Rate":
[
{"SCAC":"test1",
"CarrierName":"TEST1",
"TransitTime":"1",
"ServiceLevel":"D",
"TotalCost":"1,031.82",
"ThirdPartyCharge":"1,031.82",
"Accessorials":
{"Accessorial":
[
{"Code":"400",
"Cost":"1,655.55",
"Description":"Freight"
},
{"Code":"DSC",
"Cost":"-952.77",
"Description":"Discount"
},
{"Code":"FUE",
"Cost":"329.04",
"Description":"Fuel Surcharge"
}
]
},
"QuoteNumber":""
},
{"SCAC":"test2",
"CarrierName":"TEST2",
"TransitTime":"1",
"ServiceLevel":"D",
"TotalCost":"1,031.82",
"ThirdPartyCharge":"1,031.82",
"Accessorials":
{"Accessorial":
[
{"Code":"400",
"Cost":"1,655.55",
"Description":"Freight"
},
{"Code":"DSC",
"Cost":"-952.77",
"Description":"Discount"
},
{"Code":"FUE",
"Cost":"329.04",
"Description":"Fuel Surcharge"
}
]
},
"QuoteNumber":""
}
]
},
"AverageTotalCost":"1,031.82"
}
}
I have parsed the response data so that there is less information to work with, especially since I only need the Accessorial Costs. The parsed response looks like
[
{
"SCAC": "test1",
"CarrierName": "TEST1",
"TransitTime": "1",
"ServiceLevel": "D",
"TotalCost": "1,031.82",
"ThirdPartyCharge": "1,031.82",
"Accessorials": {
"Accessorial": [
{
"Code": "400",
"Cost": "1,655.55",
"Description": "Freight"
},
{
"Code": "DSC",
"Cost": "-952.77",
"Description": "Discount"
},
{
"Code": "FUE",
"Cost": "329.04",
"Description": "Fuel Surcharge"
}
]
},
"QuoteNumber": ""
},
{
"SCAC": "test2",
"CarrierName": "TEST2",
"TransitTime": "1",
"ServiceLevel": "D",
"TotalCost": "1,031.82",
"ThirdPartyCharge": "1,031.82",
"Accessorials": {
"Accessorial": [
{
"Code": "400",
"Cost": "1,655.55",
"Description": "Freight"
},
{
"Code": "DSC",
"Cost": "-952.77",
"Description": "Discount"
},
{
"Code": "FUE",
"Cost": "329.04",
"Description": "Fuel Surcharge"
}
]
},
"QuoteNumber": ""
}
]
The problem I am facing is that I will never know how many Rate items will come back in the response data, nor will I know the exact amount of Accessorial Costs. I'm hoping to capture the Rate child node counts and the Accessorial child node counts per Rate. Here's what I have so far.
Root rootObject = Newtonsoft.Json.JsonConvert.DeserializeObject<Root>(responseFromServer);
//rate stores the parsed response data
JArray rate = (JArray)JObject.Parse(responseFromServer)["RatingResponse"]["Rates"]["Rate"];
var rate2 = rate.ToString();
//this for loop works as expected. it grabs the number of Rate nodes (in this example, 2)
for (int i = 0; i < rate.Count(); i++)
{
dynamic test2 = rate[i];
//this is where I'm struggling
dynamic em = (JArray)JObject.Parse(test2)["Accessorials"]["Accessorial"].Count();
for (int j = 0; j < em; j++)
{
string test3 = test2.Accessorials.Accessorial[j].Cost;
System.IO.File.AppendAllText(logPath, Environment.NewLine + test3 + Environment.NewLine);
}
}
I apologize in advance for the bad formatting and odd variable names - I'm obviously still testing the functionality, so I've been using random variables.
Where I'm struggling (as notated above) is getting to the Accessorial node to count how many items are in its array. I was thinking I could parse the first array (starting with SCAC data) and extend down to the Accessorial node, but I'm not having any luck.
Any help is GREATLY appreciated, especially since I am new to this type of code and have spent the majority of the day trying to resolve this.
you can try this
var rates = (JArray)JObject.Parse(json)["RatingResponse"]["Rates"]["Rate"];
var costs = rates.Select(r => new
{
CarrierName = r["CarrierName"],
Costs = ((JArray)((JObject)r["Accessorials"])["Accessorial"])
.Where(r => (string)r["Description"] != "Discount")
.Select(r => (double)r["Cost"]).Sum()
}).ToList();
result
[
{
"CarrierName": "TEST1",
"Costs": 1984.59
},
{
"CarrierName": "TEST2",
"Costs": 1984.59
}
]

Json Path property filter structure

newtonsoft version 13.0.1
given the object data which is a JToken with the content of:
{
"myString": "demo2",
"myNumber": 2.2,
"myInteger": 20,
"myObject": {
"myObject": {
"myArray": [
2,
20,
200,
2000
]
},
"myArray": [
2,
20,
200,
2000
]
},
"myArray": [
2,
20,
200,
2000
],
"myBoolean": true,
"myNull": null
}
and the selecttokens command like this.
data.SelectTokens("$..myObject[?(#.myArray)]")
I expect to get one object back. but it doesn't return any. Is there something I do wrong here?
if I try it on https://jsonpath.com/ it will return me an object.
or should I test it like $..[?(#.myObject.myArray)]

Avoid unboxing for vectors with 1 value

For an API I wish to push data to, I need to avoid unboxing to happen on specific values.
Consider the following input:
library(jsonlite)
lsA <- list(propertyName = "listA",
Values = c("x"))
lsB <- list(propertyName = "listB",
Values = c("a","b","c"))
lsC <- list(propertyName = "listC",
min = 1,
max = 3)
I want my output to be like this:
[
{
"propertyName": "listA",
"Values": ["x"]
},
{
"propertyName": "listB",
"Values": ["a", "b", "c"]
},
{
"propertyName": "listC",
"min": 1,
"max": 3
}
]
However, when I do this:
lsTest <- list()
lsTest <- list.append(lsTest,I(lsA),lsB,lsC)
jsonTest <- jsonlite::toJSON(lsTest,auto_unbox = TRUE, pretty = TRUE)
jsonTest
I'm getting this (notice the unboxed value for listA):
[
{
"propertyName": "listA",
"Values": "x"
},
{
"propertyName": "listB",
"Values": ["a", "b", "c"]
},
{
"propertyName": "listC",
"min": 1,
"max": 3
}
]
How can I avoid specific one-element vectors to be unboxed during the toJSON conversion?
EDIT: cwthom kindly resolved it. Just change c("x") to list("x"). It works for lists with multiple items as well, and only add some additional new lines, which appear to be cosmetics only and did not have any negative impact on the end result on my end.

Mapbox Distance Matrix API returns all zeroes

I'm trying to implement the Mapbox Distance Matrix API as an alternative to Google, since it was becoming too expensive. I've tried to reduce the example to something minimal, with only two values:
{
code: "Ok",
distances: [
[
0,
0
]
],
durations: [
[
0,
0,
0,
0,
0,
0
]
],
destinations: [
{
distance: 404951.186070298,
name: "",
location: [
48.761423,
5.731594
]
},
{
distance: 402983.402982556,
name: "",
location: [
48.761423,
5.731594
]
}
],
sources: [
{
distance: 401905.604376238,
name: "",
location: [
48.761423,
5.731594
]
}
]
}
I see that the coordinates of the values are the same, even though they do not match the input coordinates from my URL, which are 52.08515,4.2826;52.11703,4.28716;52.11736,4.28939. The problem persists with all modes of transportation. Any help would be appreciated!
The format is lon,lat - not lat,lon - I made the same mistake but the docs are correct.

Json.net Serializing Coordinates

I am trying to create a .json file from a string of coordinates to display. I can get to the point of creating the file but the JSON Is not correct. Code follows
json="10,10;10,5;5,5;5,10"
List<Coords> eList = new List<Coords>();
Coords d = new Coords();
d.type = "Polygon";
d.coordinates = Newtonsoft.Json.JsonConvert.DeserializeObject(json);
List<def> deflist = new List<def>();
def f = new def();
f.type = "GeometryCollection";
f.geometries = d;
THE RESULTS ARE
{
"type": "GeometryCollection",
"geometries": {
"type": "Polygon",
"coordinates": [
[
[
10,
10
],
[
10,
5
],
[
5,
5
],
[
5,
10
]
]
]
}
}
-- SHOULD LOOK LIKE THIS
{
"type": "GeometryCollection",
"geometries": {
"type": "Polygon",
"coordinates": [
[[10,10],[10,5],[5,5],[5,10]]
]
}
}
the coordinates are indented and formatted in a way I can't understand. Any suggestions would be greatly appreciated.
The File is being generated to be used with Telerik RadMap Control.

Resources