Navigating a JSON Array with Newtonsoft JRaw - json.net

Is it possible for me to navigate a JSON array using the JRaw Class?
Messing around with it in Linqpad, I'm not sure how I'd be able to extract the datetime strings in the two objects contained in the json array:
string payload = #"[
{
""measureTime"": ""2019-10-19T14:43:00.8183732Z"",
""sensor1"": 342.0,
""sensor2"": 32.0,
""sensor3"": 0.0324,
""sensor4"": -893.438
},
{
""measureTime"": ""2019-10-19T19:43:00.7473732Z"",
""sensor1"": 348.0,
""sensor2"": 32.0,
""sensor3"": 0.0324,
""sensor4"": -893.438
}
]";
JRaw raw = new JRaw(payload);
raw.HasValues.Dump();
raw.Next.Dump();
raw.Children().Dump();
The output of those dumps are:
False
null
(0 items)
For context, I'm trying to use Azure API Management to examine the json contained in the body of an incoming request, and verify that all the datetime strings contained in it comport to RFC3339's date-time format. This would be very simple if I could just do:
JsonConvert.DeserializeObject<JArray>(context.Request.Body.As<string>(preserveContent: true),
new JsonSerializerSettings {DateParseHandling = DateParseHandling.None});
However, 'Newtonsoft.Json.JsonSerializerSettings' is not currently supported within APIM policy expressions
If I just use JArray.Parse(), that resulting JArray has the datetime string stored in a DateTime object, rather than the original string, which means I can't validate the format of the string as it originally came in.
I do have access to the JRaw class, and thought I might be able to make use of that somehow.

Related

Handling reads of Cosmos DB container with multiple types?

I'd like to store several different object types in a single Cosmos DB container, as they are all logically grouped and make sense to read together by timestamp to avoid extra HTTP calls.
However, the Cosmos DB client API doesn't seem to provide an easy way of doing the reads with multiple types. The best solution I've found so far is to write your own CosmosSerializer and JsonConverter, but that feels clunky: https://thomaslevesque.com/2019/10/15/handling-type-hierarchies-in-cosmos-db-part-2/
Is there a more graceful way to read items of different types to a shared base class so I can cast them later, or do I have to take the hit?
Thanks!
The way I do this is to create the ItemQueryIterator and FeedResponse objects as dynamic and initially read them untyped so I can inspect a "type" property that tells me what type of object to deserialize into.
In this example I have a single container that contains both my customer data as well as all their sales orders. The code looks like this.
string sql = "SELECT * from c WHERE c.customerId = #customerId";
FeedIterator<dynamic> resultSet = container.GetItemQueryIterator<dynamic>(
new QueryDefinition(sql)
.WithParameter("#customerId", customerId),
requestOptions: new QueryRequestOptions
{
PartitionKey = new PartitionKey(customerId)
});
CustomerV4 customer = new CustomerV4();
List<SalesOrder> orders = new List<SalesOrder>();
while (resultSet.HasMoreResults)
{
//dynamic response. Deserialize into POCO's based upon "type" property
FeedResponse<dynamic> response = await resultSet.ReadNextAsync();
foreach (var item in response)
{
if (item.type == "customer")
{
customer = JsonConvert.DeserializeObject<CustomerV4>(item.ToString());
}
else if (item.type == "salesOrder")
{
orders.Add(JsonConvert.DeserializeObject<SalesOrder>(item.ToString()));
}
}
}
Update:
You do not have to use dynamic types if want to create a "base document" class and then derive from that. Deserialize into the documentBase class, then check the type property check which class to deserialize the payload into.
You can also extend this pattern when you evolve your data models over time with a docVersion property.

Newtonsoft Json JsonSerializationException with simple string

My datasource creates the JSON representing an array of integers as "1,2,3,4,5". I can't do anything about this (Like changing it to [1,2,3,4,5]), it is an enterprise CMS that we have to just deal with.
I'm trying to read up on how the newtonsoft ToObject method handles the following code:
JValue theValue = new JValue("1,2,3")
List<int> x = theValue.ToObject<List<int>>();
I get a Newtonsoft.Json.JsonSerializationException. Could not cast or convert from System.String to System.Collections.Generic.List`1[System.String]. I understand this fully, but I'd like to know if the Newtonsoft JSON libraries have a built in way to convert from a comma delimited string to a List.
I'd like to think there's a better way than trying to check if the variable is a comma delimited list or not and then converting it to a List<> manually, or maybe a JArray, but I've been wrong before !
EDIT
I wanted to share my solution:
dynamic theValue = new JValue("1,2,3,4"); /// This is just passed in, i'm not doing this on purpose. Its to demo.
if (info.PropertyType == typeof (List<int>))
{
if (info.CanWrite)
{
if (theValue.GetType() == typeof (JValue) && theValue.Value is string)
{
theValue = JArray.Parse("[" + theValue.Value + "]");
}
info.SetValue(this, theValue.ToObject<List<int>>());
}
} else {
// do other things
You have three problems from what I can see:
You should be using JArray not JValue. You are intending this to be an array of things, so you need to use the equivalent class in Newtonsoft to represent an array. (A JValue, as best I can tell, represents a simple type--e.g. string, number, Date, etc.)
You should use the Parse method versus using the constructor. Parse will read the content of the string as an array, however...
...in order for it to do that, you will need to surround the data that you get with the square brackets or JArray can't correctly the parse the data. There is no need to fiddle with the CMS; just do a string concat before you parse.
e.g.
JArray theValue = JArray.Parse("[" + "1,2,3" + "]");

Combine one field in a JSON object array to comma-delimited string in ASP.NET

I have a JSON object array like this which is being given via AJAX from client side.
[{"aid":"6038","testid":"162","testtype":"0"},
{"aid":"6037","testid":"162","testtype":"1"},
{"aid":"5763","testid":"162","testtype":"0"},
{"aid":"5772","testid":"162","testtype":"1"},
{"aid":"5773","testid":"162","testtype":"1"}]
I've a server side class to deserialize the above JSON as below.
Public Class ComparisonAttributes
Public testid, attributeid, testtype As Integer
End Class
So I deserialise the JSON as
Dim ca() As ComparisonAttributes
ca = js.Deserialize(Of ComparisonAttributes())(attributes)
So I've got the real JSON object array.
But my requirement is to combine all aid in the JSON object to a comma delimitted string based on a condition like testtype=1
So the result should be 6037,5772,5773
I was able to made that using a loop across the JSON object like this
For Each cad As ComparisonAttributes In ca
''' Here i did the condition check and append to a string array
Next
But I believe there is a one liner like we do combining rows in Datatable using LINQ or similar way without a loop
A LINQ query like this maybe should help:
Dim result = ca.Where(Function(item) item.testtype = 1).Select(Function(item) item.aid).ToArray()
or something like:
Dim result = (From ca In item Where item.testtype = 1item.aid).ToArray()

ExtJs 4 Displaying WCF DateTime

I can't figure out how convert the datetime that wcf outputs into a datetime that ExtJs can use. I have found lots of articles about this but they are all for ExtJs 3 and I couldn't get it to work with 4.
I did find this code but I don't know how I could use it to convert everything in my JsonStore.
//this method is used to convert the MS JSON date format to the ExtJS Grid Date Column Value
function dateFormatter(dt) {
/// <summary>this method is used to convert the MS JSON date format to the ExtJS Grid Date Column Value</summary>
/// <param name="dt">Actual JSON Date Value</param>
try {
//microsoft JSON date format needs to convert into Javascript date
var newdata = dt.replace(/\/Date\((-?[0-9]+)([+-][0-9]+)?\)\//g, "new Date($1)");
newdata = eval('(' + newdata + ')');
return newdata.format('m/d/Y');
}
catch (e) {
return dt;
}
}
Unlike Ext JS 3, Ext JS 4 does not extend the native Date object. Instead it provides Ext.Date. So instead of:
date.format('m/d/Y');
you would instead use:
Ext.Date.format(date, 'm/d/Y');
Additionally using eval() is a really bad idea most of the time. This code is no exception.
And if you drop eval, the try-catch is also not needed.
Finally, a function that both parses a date and converts it to another format seems to be doing too much. Often you will want to display the same date in different formats in different parts of your app. Therefore I would rather just have a function that parses the WCF date format into JavaScript Data object. And then use convert the Date object into particular string format at the very place where it's needed.
Removing all extraneous stuff, this is what I get:
function parseWcfDate(dt) {
var milliseconds = dt.replace(/\/Date\((-?[0-9]+)([+-][0-9]+)?\)\//, "$1");
return new Date(parseInt(milliseconds, 10));
}
Anyway, all this is too much trouble... Ext JS has built-in support for parsing WCF formatted dates:
Ext.Date.parse("/Date(1234567894560)/", "MS");
Also see:
How to handle json DateTime returned from WCF Data Services (OData)
How do I format a Microsoft JSON date?
Use JSON.NET with JavaScriptDateConverter.

List Keys in JScript object using VBScript (Classic ASP)

I am using the JSON2 script in an asp page to parse JSON post data.
After parsing the data, I have an object in VBScript that allows for notations such as:
jsonData.key
I wish to parse through all the keys, however, I have no knowledge of the key names.
How would I go about doing this?
Example JSON:
{ "dbtable":"TABLE1", "dbcommand": "INSERT", "dbfilter": "ID" }
Thanks
You need to enumerate the property names of the object however this is a very alien thing to do in VBScript. You will need to build some other Jscript functions to assist converting the object into something more easily consumed in VBScript.
If the data is really as simplistic as the example in the question then you could use this function:-
function toDictionary(o)
{
var result = Server.CreateObject("Scripting.Dictionary");
for (var key in o)
result.Add(key, o[key]);
return result;
}
Now in VBScript:-
Dim myData: Set myData = toDictionary(jsonData);
For Each Key In myData
'' // Each Key is a property for jsonData
Next

Resources