Related
I have the following code that loops through json files in a directory and creates a csv file with following records:
results.csv
File Name Page Practice Name
fileXYZ.json 1 XYZ & Co
fileAB2.json 1 ABC & Co
file1.json 1 Associates & Co
However, if i stop execution and rerun the program again, what happens is that the same records get inserted in the csv file again, resulting in:
File Name Page Practice Name
fileXYZ.json 1 XYZ & Co
fileAB2.json 1 ABC & Co
file1.json 1 Associates & Co
fileXYZ.json 1 XYZ & Co
fileAB2.json 1 ABC & Co
file1.json 1 Associates & Co
How do i check if the record already exists (i.e. each field is the same of the fields being inserted) and replace it (or basically dont append it again?) for example, if i were to run the program again because there was a change in file1.json and also because there was a new file added to the directory, the new csv should look like this:
results.csv:
File Name Page Practice Name
fileXYZ.json 1 XYZ & Co
fileAB2.json 1 ABC & Co
file1.json 1 Corpum & Co
file32.json 1 FirmA
code:
using ChoETL;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
static void Main(string[] args)
{
//Output to CSV
foreach (var jsonFile in Directory.GetFiles(jsonFilesPath))
{
JsonToCsv(jsonFile, csvFilePath);
}
}
public static string fieldValue(IEnumerable<dynamic> lines, string nameOfField, bool throwException = false)
{
var skipped = lines.SkipWhile(l => l.text != nameOfField);
switch (throwException)
{
case true:
var enumerator = lines.GetEnumerator();
while (enumerator.MoveNext())
{
if (skipped.Count() == 0)
return skipped.Skip(1).First().text;
else
throw new InvalidDataException("Odd number of items found in IEnumerable<>");
}
break;
case false:
// Skip(#) to skip over the unnecessary Lines,
// such as "Account Information", preceding "Practice Name".
return skipped.Skip(1).First().text;
break;
default:
Console.WriteLine("Default case");
break;
}
// Returning null isn't recommended, but it does fix the error "not all code paths return a value"
return null;
}
public static void JsonToCsv(string jsonInputFile, string csvFile)
{
using (var p = new ChoJSONReader(jsonInputFile).WithJSONPath("$..readResults"))
{
using (var fs = new FileStream(csvFile, FileMode.Append, FileAccess.Write))
{
using (var writer = new ChoCSVWriter(fs))
{
writer.WithField("FileName", fieldName: "File Name")
.WithField("Page")
.WithField("PracticeName", fieldName: "Practice Name");
if (fs.Position == 0) // we don't need header if file already existed before
{
writer.WithFirstLineHeader();
}
// Limit the result to page 1 since the fields below only exist on the 1st page
writer.Write(p
.Where(r1 => r1.page == 1)
.Select(r1 =>
{
var lines = (dynamic[])r1.lines;
return new
{
FileName = jsonInputFile,
Page = r1.page,
PracticeName = //lines[6].text,
fieldValue(lines, "Practice Name"),
};
}
));
}
fs.Write(Environment.NewLine); // append new line carrier so we don't write to the same line when file reopened for writing
}
}
}
Sample JSON file
{
"status": "succeeded",
"createdDateTime": "2020-10-30T15:56:11Z",
"lastUpdatedDateTime": "2020-10-30T15:56:12Z",
"analyzeResult": {
"version": "3.0.0",
"readResults": [
{
"page": 1,
"angle": 0.086,
"width": 684,
"height": 272,
"unit": "pixel",
"lines": [
{
"boundingBox": [
7,
6,
196,
5,
196,
24,
7,
25
],
"text": "Account Information",
"words": [
{
"boundingBox": [
10,
7,
83,
7,
81,
24,
7,
26
],
"text": "Account",
"confidence": 0.981
},
{
"boundingBox": [
87,
7,
196,
6,
196,
24,
85,
24
],
"text": "Information",
"confidence": 0.939
}
]
},
{
"boundingBox": [
120,
56,
223,
57,
223,
70,
120,
70
],
"text": "Practice Name",
"words": [
{
"boundingBox": [
120,
57,
176,
57,
176,
70,
120,
71
],
"text": "Practice",
"confidence": 0.982
},
{
"boundingBox": [
179,
57,
222,
57,
222,
71,
179,
70
],
"text": "Name",
"confidence": 0.985
}
]
},
{
"boundingBox": [
236,
62,
390,
62,
390,
77,
236,
77
],
"text": "Some Practice Name",
"words": [
{
"boundingBox": [
236,
62,
277,
62,
277,
78,
236,
78
],
"text": "Some",
"confidence": 0.987
},
{
"boundingBox": [
280,
62,
340,
62,
341,
78,
280,
77
],
"text": "Practice",
"confidence": 0.984
},
{
"boundingBox": [
343,
62,
390,
62,
390,
78,
344,
78
],
"text": "Name",
"confidence": 0.987
}
]
},
{
"boundingBox": [
107,
102,
223,
102,
223,
115,
107,
115
],
"text": "Owner Full Name",
"words": [
{
"boundingBox": [
108,
103,
151,
102,
151,
116,
107,
116
],
"text": "Owner",
"confidence": 0.985
},
{
"boundingBox": [
154,
102,
177,
102,
176,
116,
153,
116
],
"text": "Full",
"confidence": 0.954
},
{
"boundingBox": [
180,
102,
224,
103,
223,
116,
179,
116
],
"text": "Name",
"confidence": 0.987
}
]
},
{
"boundingBox": [
237,
104,
298,
104,
298,
119,
237,
119
],
"text": "Bob Lee",
"words": [
{
"boundingBox": [
238,
104,
266,
104,
266,
119,
238,
120
],
"text": "Bob",
"confidence": 0.987
},
{
"boundingBox": [
269,
104,
298,
105,
298,
120,
269,
119
],
"text": "Lee",
"confidence": 0.987
}
]
},
{
"boundingBox": [
136,
147,
223,
147,
223,
160,
137,
161
],
"text": "Owner Email",
"words": [
{
"boundingBox": [
137,
148,
181,
147,
181,
161,
137,
162
],
"text": "Owner",
"confidence": 0.985
},
{
"boundingBox": [
184,
147,
224,
147,
224,
161,
184,
161
],
"text": "Email",
"confidence": 0.985
}
]
},
{
"boundingBox": [
239,
144,
361,
144,
361,
162,
239,
162
],
"text": "bob#gmail.com",
"words": [
{
"boundingBox": [
240,
145,
362,
146,
361,
163,
240,
163
],
"text": "bob#gmail.com",
"confidence": 0.974
}
]
},
{
"boundingBox": [
137,
193,
224,
193,
224,
208,
137,
208
],
"text": "Server Setup",
"words": [
{
"boundingBox": [
137,
194,
179,
194,
179,
208,
137,
208
],
"text": "Server",
"confidence": 0.985
},
{
"boundingBox": [
182,
194,
224,
194,
224,
209,
182,
208
],
"text": "Setup",
"confidence": 0.985
}
]
},
{
"boundingBox": [
276,
188,
340,
192,
339,
211,
275,
209
],
"text": "cloud",
"words": [
{
"boundingBox": [
297,
192,
339,
194,
339,
211,
297,
211
],
"text": "cloud",
"confidence": 0.933
}
]
},
{
"boundingBox": [
376,
187,
461,
191,
460,
212,
376,
211
],
"text": "Location",
"words": [
{
"boundingBox": [
394,
191,
460,
196,
459,
211,
394,
211
],
"text": "Location",
"confidence": 0.844
}
]
},
{
"boundingBox": [
500,
189,
666,
192,
665,
212,
499,
211
],
"text": "LIcentral (multi-location)",
"words": [
{
"boundingBox": [
501,
190,
567,
195,
567,
212,
500,
212
],
"text": "LIcentral",
"confidence": 0.665
},
{
"boundingBox": [
572,
195,
665,
195,
665,
212,
571,
212
],
"text": "(multi-location)",
"confidence": 0.899
}
]
},
{
"boundingBox": [
21,
238,
224,
238,
223,
255,
21,
253
],
"text": "Number of Locations Enrolling",
"words": [
{
"boundingBox": [
21,
239,
76,
239,
76,
253,
21,
253
],
"text": "Number",
"confidence": 0.985
},
{
"boundingBox": [
79,
239,
92,
239,
92,
253,
79,
253
],
"text": "of",
"confidence": 0.983
},
{
"boundingBox": [
95,
239,
161,
239,
161,
254,
95,
253
],
"text": "Locations",
"confidence": 0.981
},
{
"boundingBox": [
164,
239,
224,
239,
223,
256,
163,
254
],
"text": "Enrolling",
"confidence": 0.983
}
]
},
{
"boundingBox": [
273,
237,
289,
239,
288,
257,
272,
255
],
"text": "1",
"words": [
{
"boundingBox": [
278,
237,
290,
239,
287,
257,
276,
255
],
"text": "1",
"confidence": 0.981
}
]
},
{
"boundingBox": [
337,
239,
670,
239,
670,
253,
337,
252
],
"text": "*If more than 1 location, add info on the locations form",
"words": [
{
"boundingBox": [
338,
239,
347,
239,
347,
252,
338,
252
],
"text": "*If",
"confidence": 0.874
},
{
"boundingBox": [
350,
239,
384,
239,
384,
253,
350,
252
],
"text": "more",
"confidence": 0.983
},
{
"boundingBox": [
386,
239,
416,
239,
416,
253,
386,
253
],
"text": "than",
"confidence": 0.986
},
{
"boundingBox": [
419,
239,
422,
239,
422,
253,
419,
253
],
"text": "1",
"confidence": 0.635
},
{
"boundingBox": [
425,
239,
478,
239,
478,
253,
425,
253
],
"text": "location,",
"confidence": 0.955
},
{
"boundingBox": [
481,
239,
506,
239,
506,
253,
481,
253
],
"text": "add",
"confidence": 0.986
},
{
"boundingBox": [
509,
239,
533,
239,
533,
253,
509,
253
],
"text": "info",
"confidence": 0.981
},
{
"boundingBox": [
535,
239,
551,
239,
552,
253,
535,
253
],
"text": "on",
"confidence": 0.988
},
{
"boundingBox": [
554,
239,
574,
239,
575,
253,
554,
253
],
"text": "the",
"confidence": 0.987
},
{
"boundingBox": [
577,
239,
634,
239,
634,
253,
577,
253
],
"text": "locations",
"confidence": 0.973
},
{
"boundingBox": [
636,
239,
666,
240,
666,
253,
637,
253
],
"text": "form",
"confidence": 0.986
}
]
}
]
}
]
}
}
screenshot of csv after adding spproach 2 of Supun De Silva answer:
FYI. Sample file you provided does not work as it fails at var lines = (dynamic[])r1.lines;
Approach 1 - Rename Old File and Create a new one for data appending
1. Introduce new Function
private static void RenameIfExist(string csvFilePath)
{
if (File.Exists(csvFilePath))
{
System.IO.File.Move(csvFilePath, $"{csvFilePath}_{DateTime.Now.ToString("backup_yyyyMMdd_HHmmss")}");
}
}
2. Call the Mover Function and use Create mode in new file
public static void JsonToCsv(string jsonInputFile, string csvFile)
{
using (var p = new ChoJSONReader(jsonInputFile).WithJSONPath("$..readResults"))
{
Program.RenameIfExist(csvFile);
using (var fs = new FileStream(csvFile, FileMode.Create, FileAccess.Write))
{
try
{
using (ChoCSVWriter<dynamic> writer = new ChoCSVWriter(fs)
.WithField("FileName", fieldName: "File Name")
.WithField("Page")
.WithField("PracticeName", fieldName: "Practice Name")
.WithFirstLineHeader())
{
// Limit the result to page 1 since the fields below only exist on the 1st page
writer.Write(p
.Where(r1 => r1.page == 1)
.Select(r1 =>
{
var lines = (dynamic[])r1.lines;
return new
{
FileName = jsonInputFile,
Page = r1.page,
PracticeName = fieldValue(lines, "Practice Name"),
};
}
));
}
}
catch(Exception e)
{
throw e;
}
}
}
}
Approach 2 - Open Existing File and create a lookup structure with the data
You may need to tweak this a bit
1. Declare new struct to store a key
private static Dictionary<string, bool> processedfileStates = new Dictionary<string, bool>();
2. Pre-Loader Function
private static void LoadOldStatsIfExist(string csvFilePath)
{
if (File.Exists(csvFilePath))
{
using (var fs = new FileStream(csvFilePath, FileMode.Open, FileAccess.Read))
{
using (ChoCSVReader<dynamic> reader = new ChoCSVReader(fs).WithFirstLineHeader())
{
using (var dataReader = reader.AsDataReader())
{
while (dataReader.Read())
{
Program.processedfileStates.Add($"{dataReader[0].ToString()}_{dataReader[1].ToString()}_{dataReader[2].ToString()}", true);
}
}
}
}
}
}
3. Json to CSV fcn
public static void JsonToCsv(string jsonInputFile, string csvFile)
{
using (var p = new ChoJSONReader(jsonInputFile).WithJSONPath("$..readResults"))
{
Program.LoadOldStatsIfExist(csvFile);
using (var fs = new FileStream(csvFile, Program.processedfileStates.Count == 0 ? FileMode.Create : FileMode.Append, FileAccess.Write))
{
if (Program.processedfileStates.Count != 0)
{
fs.Write(Environment.NewLine);
}
try
{
ChoCSVWriter<dynamic> writer = new ChoCSVWriter(fs);
if (Program.processedfileStates.Count == 0)
{
writer.WithFirstLineHeader();
}
using (writer
.WithField("FileName", fieldName: "File Name")
.WithField("Page")
.WithField("PracticeName", fieldName: "Practice Name")
)
{
if (Program.processedfileStates.Count == 0)
{
writer = writer.WithFirstLineHeader();
}
// Limit the result to page 1 since the fields below only exist on the 1st page
var data = p
.Where(r1 => r1.page == 1)
.Select(r1 =>
{
var lines = (dynamic[])r1.lines;
return new
{
FileName = jsonInputFile,
Page = r1.page,
PracticeName = fieldValue(lines, "Practice Name"),
};
}
).Where(de => !processedfileStates.ContainsKey($"{de.FileName.ToString()}_{de.Page.ToString()}_{de.PracticeName.ToString()}"));
writer.Write(data);
}
}
catch (Exception e)
{
throw e;
}
}
}
}
Approach 2 - Refactored
public class OPModel
{
public string FileName { get; set; }
public long Page { get; set; }
public string PracticeName { get; set; }
}
public class Program
{
const string jsonFilesPath = "D:\\DevWork\\C#\\TempProject1\\ConsoleApp1\\data";
const string csvFilePath = "D:\\DevWork\\C#\\TempProject1\\ConsoleApp1\\output\\op.csv";
private static Dictionary<string, bool> processedfileStates = new Dictionary<string, bool>();
private static bool fileExisted = false;
private static void RenameIfExist(string csvFilePath)
{
if (File.Exists(csvFilePath))
{
System.IO.File.Move(csvFilePath, $"{csvFilePath}_{DateTime.Now.ToString("backup_yyyyMMdd_HHmmss")}");
}
}
private static void LoadOldStatsIfExist(string csvFilePath)
{
if (File.Exists(csvFilePath))
{
using (var fs = new FileStream(csvFilePath, FileMode.Open, FileAccess.Read))
{
using (ChoCSVReader<dynamic> reader = new ChoCSVReader(fs).WithFirstLineHeader())
{
using (var dTable = reader.AsDataTable())
{
foreach (DataRow row in dTable.Rows)
{
Program.processedfileStates.Add($"{row["File Name"].ToString()}_{row["Page"].ToString()}_{row["Practice Name"].ToString()}", true);
}
}
}
}
}
}
public static void Main(string[] args)
{
try
{
Program.fileExisted = File.Exists(csvFilePath);
Program.LoadOldStatsIfExist(csvFilePath);
List<OPModel> dataToWrite = new List<OPModel>();
// Persist each file to
foreach (var jsonFile in Directory.GetFiles(jsonFilesPath))
{
dataToWrite.AddRange(JsonToCsv(jsonFile));
}
if (dataToWrite.Count != 0)
{
using (var fs = new FileStream(csvFilePath, !Program.fileExisted ? FileMode.Create : FileMode.Append, FileAccess.Write))
{
try
{
ChoCSVWriter<OPModel> writer = new ChoCSVWriter<OPModel>(fs);
using (writer.WithField("FileName", fieldName: "File Name").WithField("Page").WithField("PracticeName", fieldName: "Practice Name"))
{
if (!Program.fileExisted)
{
writer = writer.WithFirstLineHeader();
}
writer.Write(dataToWrite);
}
fs.Write(Environment.NewLine);
}
catch (Exception e)
{
throw e;
}
}
}
//Output to CSV
Console.ReadKey();
}
catch (Exception ex)
{
}
}
public static string fieldValue(IEnumerable<dynamic> lines, string nameOfField, bool throwException = false)
{
var skipped = lines.SkipWhile(l => l.text != nameOfField);
switch (throwException)
{
case true:
var enumerator = lines.GetEnumerator();
while (enumerator.MoveNext())
{
if (enumerator.MoveNext())
return skipped.Skip(1).First().text;
else
throw new InvalidDataException("Odd number of items found in IEnumerable<>");
}
break;
case false:
// Skip(#) to skip over the unnecessary Lines,
// such as "Account Information", preceding "Practice Name".
return skipped.Skip(1).First().text;
default:
Console.WriteLine("Default case");
break;
}
// Returning null isn't recommended, but it does fix the error "not all code paths return a value"
return null;
}
public static List<OPModel> JsonToCsv(string jsonInputFile)
{
using (var reader = new ChoJSONReader(jsonInputFile).WithJSONPath("$..readResults"))
{
var data = reader.Where(r1 => r1.page == 1)
.Select(r1 =>
{
var lines = (dynamic[])r1.lines;
return new OPModel
{
FileName = jsonInputFile,
Page = r1.page,
PracticeName = Program.fieldValue(lines, "Practice Name")
};
}
).Where(de => !processedfileStates.ContainsKey($"{de.FileName.ToString()}_{de.Page.ToString()}_{de.PracticeName.ToString()}")).ToList();
return data;
}
}
}
I've spent a while trying to work out how to desterilise this JSON file and get each products
ID,NAME,COLLECTION COST, AND WEATHER ITS ON OFFER
Im currently attempting this with Newtonsoft.Json in a C# class.
could someone please point me in the right direction.
Many thanks
for the JSON text visit:
https://pastebin.com/bkQwpsAy
{
"_embedded": {
"products": [{
"uuid": "74f1501f-4a52-490a-b2b9-668f16e2db95",
"createdAt": "2020-04-20T13:44:22.000+00:00",
"itemId": "DRN543",
"altItemGroupId": "",
"popularityScore": 101.22,
"itemName": "Coca-Cola Bottles (GB) 6x1.5L",
"jsonFriendlyItemName": "Coca-Cola Bottles (GB) 6x1.5L",
"seoFriendlyItemName": "coca-cola-bottles-gb-6x1-5l",
"brand": "Coca Cola",
"imageLinks": ["https://jjproducts.global.ssl.fastly.net/jjfoodservice/image/upload/v1588074299/products/DRN543/_S/ggktoxjzbplky4uovec4.jpg"],
"price": 9.99,
"depth": 29.0,
"height": 32.0,
"itemNetWeight": 9.0,
"jadMobileItemName": "Coca Cola (GB) 6x1.5L",
"category1Id": "100005",
"category2Id": "200261",
"category3Id": "300194",
"category4Id": "400084",
"category5Id": "",
"category1Name": "Drinks",
"category2Name": "Soft Drinks",
"category3Name": "Fizzy Drinks",
"category4Name": "Cola",
"category5Name": "",
"origin": "United Kingdom",
"catchOrigin": "",
"productDescription": "",
"sellingPoints": "Coca Cola\nCocaCola",
"shelfLife": 135,
"sizeOrCut": "6x1.5l",
"qtyPerLayer": 20.0,
"standardPalletQty": 80.0,
"unitVolume": 17632.0,
"width": 19.0,
"allergensDeclaration": "",
"storageCondition": "Store cool and dry.",
"storedAt": "2020-11-03T23:52:28.789210Z",
"branches": [{
"locationId": "EN-MW",
"locationName": "Enfield Branch",
"warehouseArea": "DA",
"warehouseZone": "GZ"
}, {
"locationId": "LS-MW",
"locationName": "Leicester Branch",
"warehouseArea": "DA",
"warehouseZone": "GZ"
}
],
"branchesBeforeLastUpdate": [{
"locationId": "EN-MW",
"locationName": "Enfield Branch",
"warehouseArea": "DA",
"warehouseZone": "GZ"
}, {
"locationId": "LS-MW",
"locationName": "Leicester Branch",
"warehouseArea": "DA",
"warehouseZone": "GZ"
}
],
"video": [],
"categoryList": "[{\"id\":\"100005\",\"name\":\"Drinks\"},{\"id\":\"200261\",\"name\":\"Soft Drinks\"},{\"id\":\"300194\",\"name\":\"Fizzy Drinks\"}]",
"categoryId": "100005,200261,300194",
"categoryName": "Drinks,Soft Drinks,Fizzy Drinks",
"categoryNormalised": "[Cola Drinks Fizzy Soft]",
"productFeatures": ["Popular", "Ambient", "Vegan", "Vegetarian"],
"unitSize": "1.5L",
"unitPriceDivider": 0.16666,
"unitPriceTypeDisplayText": "each",
"offer": {
"itemId": "DRN543",
"promoForCc": false,
"promoTagId": "Monthly",
"promoTag": "Monthly Special Promotions",
"promoEnd": "31/12/2020",
"promoDisAmt": 0,
"promoDisPct": 0,
"promoDiscountText": [],
"id": "DRN543"
},
"delivery": {
"price": 8.29,
"priceInc": 8.29,
"unitPriceDisplay": "£1.38 each",
"step": 1.0,
"max": 15.0,
"collection": false
},
"collection": {
"price": 7.29,
"priceInc": 7.29,
"unitPriceDisplay": "£1.21 each",
"step": 1.0,
"max": 15.0,
"collection": true
},
"previouslyPurchased": false,
"favourite": false,
"available": true,
"new": false,
"popular": true,
"popularOnCategory1": true,
"popularOnCategory2": true,
"popularOnCategory3": true,
"ageRestriction": false,
"halal": false,
"vegan": true,
"vegeterian": true,
"numberOfPackage": 6,
"numberOfUnitsInPackage": 1.5,
"unitType": "litre",
"CCMAltItemGroup": "",
"JJeBrand": "Coca Cola",
"JadConsumableDepth": 0.0,
"JadConsumableHeight": 0.0,
"JadConsumableWidth": 0.0,
"JJeCategory1Id": "100005",
"JJeCategory2Id": "200261",
"JJeCategory3Id": "300194",
"JJeCategory4Id": "400084",
"JJeCategory5Id": "",
"JJeCategory1": "Drinks",
"JJeCategory2": "Soft Drinks",
"JJeCategory3": "Fizzy Drinks",
"JJeCategory4": "Cola",
"JJeCategory5": "",
"JJeCookingInstruction": "Best served chilled.",
"JJeIngredients": "Carbonated Water, Sugar, Colour (Caramel E150d), Phosphoric Acid, Natural Flavourings including Caffeine.",
"JadIngredientsHTML": "Carbonated Water, Sugar, Colour (Caramel E150d), Phosphoric Acid, Natural Flavourings including Caffeine.",
"JJeOrigin": "United Kingdom",
"JadCatchOrigin": "",
"JJeProductDescription": "",
"JJeSellingPoints": "Coca Cola\nCocaCola",
"JJeShelfLife": 135,
"JJeSizeOrCut": "6x1.5L",
"JadAllergensDeclaration": "",
"JadStorageCondition": "Store cool and dry.",
"JJeEnergyKJ": 180.0,
"JJeEnergyKCAL": 42.0,
"JJeFatG": "0",
"JadFatSaturatesG": "0",
"JJeCarbohydrateG": "10.6",
"JadCarbohydrateSugarsG": "10.6",
"JJeProteinG": "0",
"JadSodiumG": "0",
"IsAgeRestriction": false,
"IsHalal": false,
"IsVegan": true,
"IsVegeterian": true
}
]
},
"_links": {
"maintenance-message": {
"href": "[]"
},
"announcement-message": {
"href": "[]"
}
},
"page": {
"size": 12,
"totalElements": 18,
"totalPages": 2,
"number": 0
}
}
public static List<JJs.ITEMS> JJSGetProductHTML(String Term)
{
string url = "https://www.website.com/api/product-search-agg/api/v1/product/websearch?b=DG-MW&page=0&q=" + Term+ "&size=12&sortType=search&format=json";
WebClient WC = new WebClient();
string JSON = WC.DownloadString(url);
var onject,= JsonConvert.DeserializeObject<dynamic>(JSON);
string s = onject._embedded.products[0].ToString();
List<JJs.ITEMS> products = new List<JJs.ITEMS>();
foreach (var m in onject._embedded.products)
{
JJs.ITEMS newitem = new JJs.ITEMS();
newitem.Name = m.jsonFriendlyItemName.ToString();
newitem.itemId = m.itemId.ToString();
newitem.price = m.collection.price.ToString();
try
{ m.offer.ToString(); newitem.Promoend = m.offer.promoEnd.ToString(); newitem.Promo = true; }
catch
{ newitem.Promo = false; };
products.Add(newitem);
}
return products;
}
As I didnt want all the feilds, i serialised it then used ".jsonFriendlyItemName",".itemId".. to only get the values I was looking for
thanks #JaromandaX, # Peter B and #dbc for your help
If I wanted to index into price or galleryId in this json file:
{
"searchId": null,
"listings": [{
"sid": 0,
"id": 25,
"status": 3,
"art": {
"sid": 0,
"artId": 24,
"token": "v",
"name": "A",
"description": "F",
"width": 18.0000,
"height": 24.0000,
"metricWidth": 0.4572,
"metricHeight": 0.6096,
"mediaType": "",
"fullSizeImageUrl": "http",
"thumbnailImageUrl": "http",
"artist": {
"token": null,
"firstName": "V",
"lastName": "G",
"visibleInSearch": false,
"inventoryVisibleInSearch": false
}
},
"galleryId": 1,
"price": 1750,
"listed": "2020-01-18T21:49:41.447"
}]
would this be the correct syntax?
{
for (int i = 0; i < itemData[0]["listings"].Count; i++)
{
database.Add(new Art(itemData[0]["listings"][i]["galleryId"].ToString(),
(int)itemData[0]["listings"][i]["price"]));
#PhilippLenssen you were right, the json was incomplete and not all objects had the field galleryId - this is what broke my code. Thanks for making me look through the entire file!
I have Two Json returned from Web API which contain dynamic size array "contacts" and "amenities".
Normally I will access the fixed size array "results" in Json with the following code as I am the on fix the size.
string json = _obj.GetJsonResult(url);
Hotel hotel = Newtonsoft.Json.JsonConvert.DeserializeObject<Hotel>(json);
hotelName = hotel.results[0].property_name;
I have tried the following Link and following code to get the dynamic array size back but it don't seem to be working.
var jObject = JObject.Parse(json);
JArray jArray = (JArray)jObject["hotel.results[0].contacts"];
int length = jArray.Count;
Json One
{
"results": [
{
"property_code": "FGPENOTP",
"property_name": "Olive Tree Penang",
"location": {
"latitude": 5.32708,
"longitude": 100.27944
},
"address": {
"line1": "No 76 Jalan Mahsuri",
"city": "Bayan Lepas",
"postal_code": "11950",
"country": "MY"
},
"total_price": {
"amount": "265.00",
"currency": "MYR"
},
"min_daily_rate": {
"amount": "250.00",
"currency": "MYR"
},
"contacts": [
{
"type": "PHONE",
"detail": "+6046377777"
},
{
"type": "FAX",
"detail": "+6046377788"
}
],
"amenities": [
{
"amenity": "RESTAURANT",
"ota_code": 76,
"description": "Restaurant"
},
{
"amenity": "ELEVATORS",
"ota_code": 33,
"description": "Elevators"
},
{
"amenity": "LAUNDRY_SERVICE",
"ota_code": 58,
"description": "Laundry/Valet service"
},
{
"amenity": "PARKING",
"ota_code": 68,
"description": "Parking"
},
{
"amenity": "ROOM_SERVICE",
"ota_code": 77,
"description": "Room service"
},
{
"amenity": "SAFE_DEPOSIT_BOX",
"ota_code": 78,
"description": "Safe deposit box"
},
{
"amenity": "OUTDOOR_POOL",
"ota_code": 66,
"description": "Outdoor pool"
},
{
"amenity": "BALLROOM",
"ota_code": 191,
"description": "Ballroom"
}
],
"awards": [
{
"provider": "Local Star Rating",
"rating": "4"
}
],
"images": [],
"rooms": [
{
"booking_code": "A1KBAR",
"room_type_code": "A1K",
"rate_plan_code": "BAR",
"total_amount": {
"amount": "265.00",
"currency": "MYR"
},
"rates": [
{
"start_date": "2018-06-15",
"end_date": "2018-06-16",
"currency_code": "MYR",
"price": 250
}
],
"descriptions": [
"BEST AVAILABLE RATE",
"DELUXE ROOM/ KING OR TWIN SIZED BED/ 28 SQM/",
"FREE WI FI"
],
"room_type_info": {
"room_type": "Room with bath - Superior",
"bed_type": "King",
"number_of_beds": "1"
},
"rate_type_code": "BAR"
}
],
"_links": {
"more_rooms_at_this_hotel": {
"href": "https://api.sandbox.amadeus.com/v1.2/hotels/FGPENOTP?apikey=pa3lM5UhJAZ0AJfzlZHcAKdiGVBA90wA&check_in=2018-06-15&check_out=2018-06-16&lang=EN¤cy=MYR&referrer=more_rooms_at_this_hotel"
}
}
}
]
}
Json Two
{
"results": [
{
"property_code": "WWKULAPT",
"property_name": "Sama Sama Hotel Klia",
"location": {
"latitude": 2.75803,
"longitude": 101.7041
},
"address": {
"line1": "Jalan Cta 4b",
"city": "Selangor",
"postal_code": "64000",
"country": "MY"
},
"total_price": {
"amount": "625.00",
"currency": "MYR"
},
"min_daily_rate": {
"amount": "625.00",
"currency": "MYR"
},
"contacts": [
{
"type": "PHONE",
"detail": "60-3-87873333"
},
{
"type": "FAX",
"detail": "60-3-87875555"
},
{
"type": "EMAIL",
"detail": "info#samasamahotels.com"
},
{
"type": "URL",
"detail": "www.samasamahotels.com"
}
],
"amenities": [
{
"amenity": "COFFEE_SHOP",
"ota_code": 20,
"description": "Coffee shop"
},
{
"amenity": "RESTAURANT",
"ota_code": 76,
"description": "Restaurant"
},
{
"amenity": "ACCESSIBLE_FACILITIES",
"ota_code": 47,
"description": "Accessible facilities"
},
{
"amenity": "BEAUTY_SALON",
"ota_code": 107,
"description": "Beauty shop/salon"
},
{
"amenity": "CAR_RENTAL",
"ota_code": 15,
"description": "Car rental desk"
},
{
"amenity": "CHILDREN_WELCOME",
"ota_code": 218,
"description": "Children welcome"
},
{
"amenity": "ELEVATORS",
"ota_code": 33,
"description": "Elevators"
},
{
"amenity": "CURRENCY_EXCHANGE",
"ota_code": 26,
"description": "Currency exchange"
},
{
"amenity": "EXECUTIVE_FLOOR",
"ota_code": 34,
"description": "Executive floor"
},
{
"amenity": "HOTSPOTS",
"ota_code": 221,
"description": "Hotspots"
},
{
"amenity": "INTERNET_PUBLIC_AREAS",
"ota_code": 178,
"description": "Internet access in public areas"
},
{
"amenity": "JACUZZI",
"ota_code": 55,
"description": "Jacuzzi"
},
{
"amenity": "LAUNDRY_SERVICE",
"ota_code": 58,
"description": "Laundry/Valet service"
},
{
"amenity": "MASSAGE_SERVICES",
"ota_code": 61,
"description": "Massage services"
},
{
"amenity": "NON_PORNOGRAPHIC_TV",
"ota_code": 220,
"description": "Hotel does not provide pornographic films/TV"
},
{
"amenity": "PARKING",
"ota_code": 68,
"description": "Parking"
},
{
"amenity": "SAUNA",
"ota_code": 79,
"description": "Sauna"
},
{
"amenity": "SPA",
"ota_code": 84,
"description": "Spa"
},
{
"amenity": "VALET_PARKING",
"ota_code": 97,
"description": "Valet parking "
},
{
"amenity": "",
"ota_code": 46,
"description": "Hairdresser/barber"
},
{
"amenity": "POOL",
"ota_code": 71,
"description": "Pool"
},
{
"amenity": "ROOM_SERVICE",
"ota_code": 77,
"description": "Room service"
},
{
"amenity": "SAFE_DEPOSIT_BOX",
"ota_code": 78,
"description": "Safe deposit box"
}
],
"awards": [
{
"provider": "OHG",
"rating": "Deluxe"
}
],
"images": [],
"rooms": [
{
"booking_code": "DR12ZZZ",
"room_type_code": "D2T",
"rate_plan_code": "PRO",
"total_amount": {
"amount": "625.00",
"currency": "MYR"
},
"rates": [
{
"start_date": "2018-06-15",
"end_date": "2018-06-16",
"currency_code": "MYR",
"price": 625
}
],
"descriptions": [
"Sama Sama Best Available Rate GDS",
"Deluxe Twin/AC/Free WiFi/LCD TV/36SQM/",
"NonSmoking/Work Desk/Safe/Minibar"
],
"room_type_info": {
"room_type": "Room with bath - Minimum",
"bed_type": "Twin",
"number_of_beds": "2"
},
"rate_type_code": "PRO"
}
],
"_links": {
"more_rooms_at_this_hotel": {
"href": "https://api.sandbox.amadeus.com/v1.2/hotels/WWKULAPT?apikey=pa3lM5UhJAZ0AJfzlZHcAKdiGVBA90wA&check_in=2018-06-15&check_out=2018-06-16&lang=EN¤cy=MYR&referrer=more_rooms_at_this_hotel"
}
}
}
]
}
Thanks for every members here who helped.
Since you are already deserializing your JSON, all you should have to do is call hotel.results[0].contacts.Count.
This will return an integer representing the amount of items in the contacts list.
If contacts is of the array datatype, you will need to use length instead of count.
I'm trying to setup an integration point to an Automatic License Plate Recognition (ALPR) system. I'm using OpenALPR.
On the local PC there is an agent with a IP camera installed that will read the license plate and send info to the cloud. In the cloud there is a WebHook integration point that will fire each time a license plate is registered.
In the OpenALPR webpage the WebHook documentations says:
WebHooks send an HTTP POST to your URL every time a plate is received or an alert is triggered. The POST body contains the license plate data.
I've tested the integration by sending the output to a WebHook test page found on this URL: https://webhook.site/
The result is shown at the end of this post. As can be seen the output is JSON format.
I've done a RESTful service and deployed it in Azure. My problem is that when I read the result, I don't get the full JSON result. Based on the test on the http://webhook.site, I know the WebHook provider (sender) sends all JSON data so I can't figure out why it's not fully received.
If there is a better way to receive the JSON result in my web app I'm happy to hear about it. Below is my take on how to get the job done. Except it does not work ! :-D
Can anyone tell me what I'm doing wrong and why only part of the result is read?
This is the part of the code that is called on a HTTP POST to my service.
// POST: api/OpenALP
public HttpResponseMessage Post([FromBody]string value)
{
var content = Request.Content;
Request.Content.LoadIntoBufferAsync().Wait();
string jsonContent = content.ReadAsStringAsync().Result;
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK);
return response;
}
EDIT: Don't know if it's important- but the debugging was done by publishing the service as "Debug" and the attaching a debugger. The content shown below was copied out from the break point.
This is what I get in string jsonContent
" \"color\": [{\"confidence\": 92.68022918701172, \"name\": \"white\"}, {\"confidence\": 2.699702501296997, \"name\": \"silver-gray\"}, {\"confidence\": 1.8385039567947388, \"name\": \"yellow\"}, {\"confidence\": 1.024902582168579, \"name\": \"gold-beige\"}, {\"confidence\": 0.5838126540184021, \"name\": \"green\"}], \"make\": [{\"confidence\": 16.192890167236328, \"name\": \"renault\"}, {\"confidence\": 12.871005058288574, \"name\": \"mercedes-benz\"}, {\"confidence\": 7.908616065979004, \"name\": \"volkswagen\"}, {\"confidence\": 4.901283264160156, \"name\": \"opel\"}, {\"confidence\": 4.583385467529297, \"name\": \"bmw\"}], \"body_type\": [{\"confidence\": 20.72427749633789, \"name\": \"sedan-standard\"}, {\"confidence\": 18.412166595458984, \"name\": \"van-mini\"}, {\"confidence\": 17.614177703857422, \"name\": \"sedan-compact\"}, {\"confidence\": 12.435933113098145, \"name\": \"sedan-wagon\"}, {\"confidence\": 6.872223377227783, \"name\": \"suv-crossover\"}], \"year\": [{\"confidence\": 23.91012191772461, \"name\": \"2005-2009\"}, {\"confidence\": 19.78921890258789, \"name\": \"2000-2004\"}, {\"confidence\": 16.811452865600586, \"name\": \"1995-1999\"}, {\"confidence\": 11.53968620300293, \"name\": \"2010-2014\"}, {\"confidence\": 8.91786003112793, \"name\": \"1985-1989\"}], \"make_model\": [{\"confidence\": 2.5598113536834717, \"name\": \"renault_kangoo\"}, {\"confidence\": 1.564223289489746, \"name\": \"fiat_doblo\"}, {\"confidence\": 1.5174164772033691, \"name\": \"alfa-romeo_147\"}, {\"confidence\": 1.0350353717803955, \"name\": \"citroen_2cv\"}, {\"confidence\": 0.986167311668396, \"name\": \"volkswagen_caddy\"}]}, \"best_uuid\": \"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521329355349\", \"epoch_end\": 1521329358227, \"best_image_width\": 640, \"data_type\": \"alpr_group\", \"best_image_height\": 480, \"frame_end\": 865634, \"is_parked\": false, \"web_server_config\": {\"agent_label\": \"DESKTOP-B3PMA1C\", \"camera_label\": \"WebCamHKA\"}, \"best_region\": \"eu-dk\", \"uuids\": [\"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521329355147\", \"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521329355183\", \"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521329355248\", \"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521329355284\", \"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521329355349\", \"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521329355386\", \"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521329355451\", \"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521329355523\", \"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521329355558\", \"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521329355700\", \"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521329355777\", \"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521329355815\", \"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521329355889\", \"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521329356029\", \"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521329356274\", \"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521329356421\", \"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521329356598\", \"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521329356738\", \"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521329356773\", \"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521329356874\", \"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521329356909\", \"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521329357014\", \"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521329357049\", \"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521329357148\", \"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521329357387\", \"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521329357422\", \"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521329357567\", \"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521329357631\", \"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521329357734\", \"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521329357870\", \"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521329357976\", \"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521329358012\", \"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521329358048\", \"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521329358084\", \"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521329358155\", \"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521329358191\", \"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521329358227\"], \"plate_indexes\": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], \"travel_direction\": 255.1732177734375, \"country\": \"eu\", \"best_plate_number\": \"AF22454\", \"best_region_confidence\": 91.45714569091797, \"agent_version\": \"2.5.103\", \"candidates\": [{\"matches_template\": 0, \"plate\": \"AF22454\", \"confidence\": 94.99976348876953}, {\"matches_template\": 0, \"plate\": \"AF2245\", \"confidence\": 69.99081420898438}, {\"matches_template\": 0, \"plate\": \"AF224\", \"confidence\": 68.92207336425781}, {\"matches_template\": 0, \"plate\": \"A22454\", \"confidence\": 65.7693099975586}, {\"matches_template\": 0, \"plate\": \"AY22454\", \"confidence\": 65.72945404052734}, {\"matches_template\": 0, \"plate\": \"AT22454\", \"confidence\": 65.69474029541016}]}"
If I look at the output on the WebHook test site (http://webhoot.site) I get this result:
{
"epoch_start": 1521286407536,
"camera_id": 645063384,
"frame_start": 109416,
"agent_uid": "WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X",
"best_confidence": 94.99918365478516,
"company_id": "d1806fef-5549-4915-86a8-1b1f975e8df9",
"version": 2,
"agent_type": "alprd",
"best_plate": {
"plate": "AF25463",
"confidence": 94.99918365478516,
"region_confidence": 99,
"vehicle_region": {
"y": 1,
"x": 80,
"height": 479,
"width": 479
},
"region": "eu-dk",
"plate_index": 0,
"processing_time_ms": 40.263999938964844,
"candidates": [
{
"matches_template": 0,
"plate": "AF25463",
"confidence": 94.99918365478516
}
],
"coordinates": [
{
"y": 248,
"x": 286
},
{
"y": 251,
"x": 599
},
{
"y": 318,
"x": 599
},
{
"y": 314,
"x": 286
}
],
"matches_template": 0,
"requested_topn": 10
},
"vehicle": {
"orientation": [
{
"confidence": 48.20035171508789,
"name": "270"
},
{
"confidence": 26.80327606201172,
"name": "225"
},
{
"confidence": 10.317419052124023,
"name": "315"
},
{
"confidence": 5.075159072875977,
"name": "180"
},
{
"confidence": 4.022528648376465,
"name": "0"
}
],
"color": [
{
"confidence": 89.68812561035156,
"name": "blue"
},
{
"confidence": 3.044862747192383,
"name": "silver-gray"
},
{
"confidence": 2.5986762046813965,
"name": "white"
},
{
"confidence": 2.5680367946624756,
"name": "green"
},
{
"confidence": 0.8009989857673645,
"name": "purple"
}
],
"make": [
{
"confidence": 11.725887298583984,
"name": "renault"
},
{
"confidence": 10.687095642089844,
"name": "land-rover"
},
{
"confidence": 9.455676078796387,
"name": "nissan"
},
{
"confidence": 7.793033123016357,
"name": "citroen"
},
{
"confidence": 6.8527727127075195,
"name": "suzuki"
}
],
"body_type": [
{
"confidence": 19.176368713378906,
"name": "suv-crossover"
},
{
"confidence": 18.331125259399414,
"name": "suv-standard"
},
{
"confidence": 18.325965881347656,
"name": "truck-standard"
},
{
"confidence": 11.761542320251465,
"name": "sedan-wagon"
},
{
"confidence": 10.666444778442383,
"name": "sedan-compact"
}
],
"year": [
{
"confidence": 19.741708755493164,
"name": "2005-2009"
},
{
"confidence": 17.747791290283203,
"name": "2000-2004"
},
{
"confidence": 16.381860733032227,
"name": "1995-1999"
},
{
"confidence": 13.306379318237305,
"name": "1985-1989"
},
{
"confidence": 11.591310501098633,
"name": "1980-1984"
}
],
"make_model": [
{
"confidence": 7.200094223022461,
"name": "land-rover_defender"
},
{
"confidence": 2.6545894145965576,
"name": "land-rover_discovery"
},
{
"confidence": 1.7968538999557495,
"name": "toyota_land-cruiser"
},
{
"confidence": 1.6618626117706299,
"name": "suzuki_sj-samurai"
},
{
"confidence": 1.4205354452133179,
"name": "suzuki_vitara"
}
]
},
"best_uuid": "WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521286410173",
"epoch_end": 1521286411970,
"best_image_width": 640,
"data_type": "alpr_group",
"best_image_height": 480,
"frame_end": 109536,
"is_parked": false,
"web_server_config": {
"agent_label": "DESKTOP-B3PMA1C",
"camera_label": "WebCamHKA"
},
"best_region": "eu-dk",
"uuids": [
"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521286407536",
"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521286407571",
"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521286407607",
"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521286407783",
"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521286407888",
"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521286407991",
"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521286408267",
"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521286408301",
"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521286408335",
"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521286408579",
"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521286408649",
"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521286408860",
"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521286408895",
"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521286408930",
"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521286408964",
"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521286408999",
"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521286409173",
"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521286409278",
"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521286409417",
"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521286409484",
"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521286409651",
"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521286409789",
"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521286409823",
"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521286409999",
"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521286410036",
"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521286410140",
"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521286410173",
"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521286410208",
"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521286410646",
"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521286410751",
"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521286410887",
"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521286410923",
"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521286410957",
"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521286411099",
"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521286411169",
"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521286411204",
"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521286411523",
"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521286411626",
"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521286411694",
"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521286411797",
"WBFOY6ZDPZR03FGCE5C1S9J5GIH2TFH1H6QPMX7X-645063384-1521286411970"
],
"plate_indexes": [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
"travel_direction": 18.316375732421875,
"country": "eu",
"best_plate_number": "AF25463",
"best_region_confidence": 97.08333587646484,
"agent_version": "2.5.103",
"candidates": [
{
"matches_template": 0,
"plate": "AF25463",
"confidence": 94.99918365478516
},
{
"matches_template": 0,
"plate": "AF2546",
"confidence": 70.50904846191406
},
{
"matches_template": 0,
"plate": "AF254",
"confidence": 68.68018341064453
},
{
"matches_template": 0,
"plate": "AF254AF",
"confidence": 65.75811767578125
},
{
"matches_template": 0,
"plate": "A25463",
"confidence": 65.72001647949219
},
{
"matches_template": 0,
"plate": "AE25463",
"confidence": 65.68501281738281
}
]
}
EDIT:
Ohhh - I can't post an Image. I need at least 10 reputation to post it.
But I can link to it here: https://klitandersen-my.sharepoint.com/:i:/g/personal/henrik_klit-andersen_com/Ec7DQkhrcFhAgZ6wIF24MbkBgrPcbXsgSa7_msXLZDHXQw?e=cnluHm
It appears that I was on the right track thinking that this is because you have a [FromBody] string value parameter in your controller method. That seems to offset the content buffer by 1024 bytes hence why your attempt to read it as a string inside the method body yielded only part of the original request body.
You could try a few things here (at least that's the ones I can think of). Firstly, you should try to remove the parameter from. That would solve this problem right away and you would be able to just read it without any issues as you were trying now with just a single line.
var postBodyString = Request.Content.ReadAsStringAsync().Result;
Secondly, you could try to read it as a stream and reset the stream's position. If you do go with this option - make sure you use using so that everything is disposed once you are done. I know for a fact that this didn't work for me some time ago because the ReadAsStreamAsync() in Web Api is a HttpBufferlessStream and I think it doesn't support Seek operation.
var postStream = Request.Content.ReadAsStreamAsync().Result;
postStream.Seek(0, SeekOrigin.Begin);
var postBodyString = new StreamReader(postStream).ReadToEnd();
Lastly, you could try and make the parameter HttpMessageRequest which you could then read as a string.
[Route("somePost")]
[HttpPost]
public IHttpActionResult DoSomething(HttpRequestMessage request)
{
var str = request.Content.ReadAsStringAsync().Result;
return Ok();
}
Hopefully some of these options will be acceptable for you or at least get you going on the right track.