JsonDocument - Read child object - c#

I have a JSON object that I'm trying to read properties from. Here is a sample:
{"id":"335057af-a156-41c6-a0de-0cdc05856b3d",
"title":"Test 100488-100489 not included",
"code":"QWNCY47Y999",
"start":"2022-08-10T22:00:00.000Z",
"end":"2022-08-11T02:00:00.000Z",
"closeAfter":"2022-08-08T23:59:00.000Z",
"archiveAfter":"2022-11-08T22:00:00.000Z",
"timezone":"America/New_York",
"defaultLocale":"enUS",
"currency":"USD",
"registrationSecurityLevel":"Public",
"status":"Pending",
"eventStatus":"Upcoming",
"planningStatus":"In-Planning",
"testMode":true,
"planners":[{"firstName":"C","lastName":"G","email":"Noreply#events.qwerty.comx"}],
"created":"2021-06-11T09:55:57.667Z",
"lastModified":"2021-07-08T17:21:48.039Z",
"customFields":[
{"id":"f2cf4864-171f-44fa-919a-248d37e42563",
"name":"Level of Service",
"value":["Full Support"],
"type":"SingleSelect",
"order":25},
{"id":"c1539edf-a3e1-4f40-9747-e93f4fedfa5d",
"name":"Internal/External",
"value":["Internal","External"],
"type":"MultiSelect",
"order":42},
{"id":"1b525d2a-b3f8-4141-91ae-45de5ee3a2fe",
"name":"Request ID",
"value":["MRF000558"],
"type":"AutoIncrement",
"order":53}],
"category":{"name":"Conference"},
"_links":{"invitation":{"href":"http://sandbox-www.qwerty.com/d/8nqg6n/1Q"},
"agenda":{"href":"http://sandbox-www.qwerty.com/d/8nqg6n/6X"},
"summary":{"href":"http://sandbox-www.qwerty.com/d/8nqg6n"},
"registration":{"href":"http://sandbox-www.qwerty.com/d/8nqg6n/4W"}},
"virtual":false,
"format":"In-person"}
I can programmatically read string properties, but if one of the properties is another object, I can't read it.
try
{
var x1 = content2.RootElement.GetProperty("code"); // it works
var x2 = content2.RootElement.GetProperty("currency"); // it works
var x3 = content2.RootElement.GetProperty("start"); // it works
var x99 = content2.RootElement.GetProperty("summary"); // exception, key not found
var x999 = x99.GetProperty("href");
}
catch(System.Exception ex)
{
Console.WriteLine(ex.Message);
}
Ultimately, my goal is to read the summary child object and get property href.

you have a bug. "summary" goes after "_links"
this works for me
var contentObj = JObject.Parse(content);
var href = contentObj["_links"]["summary"]["href"];
output
http://sandbox-www.qwerty.com/d/8nqg6n
for you I guess it could be
var x9 = content2.RootElement.GetProperty("_links");
var x99 = x9.GetProperty("summary");
var x999 = x99.GetProperty("href").ToString();
//or just
var x999 = content2.RootElement.GetProperty("_links").GetProperty("summary").GetProperty("href").ToString();

Unless this "but if one of the properties is another object, I can't read it." means that you don't have a well defined format for your JSON file, just create an object for your JSON file and deserialize it. Then you can access it directly via that objects property.

Related

Saving Binary Data FHIR DB

I am trying to save Binary data to FHIR DB.
This is my method:
public static Patient SavePdfForms(string resource, HttpClientEventHandler messageHandler, string[] pdfForms, Patient patient, FhirClient BinaryBundleClient)
{
Bundle BinaryBundle = new Bundle();
BinaryBundle.Type = Bundle.BundleType.Collection;
try
{
foreach (var item in pdfForms)
{
Binary BinaryData = new Binary();
var bytearray = Encoding.ASCII.GetBytes(item);
BinaryData.Data = bytearray;
BinaryData.ContentType = "application/fhir+json";
var binaryResource = BinaryBundleClient.Create(BinaryData);
BinaryBundle.AddResourceEntry(BinaryData, resource + "/BundleResource/" + binaryResource.Id);
}
}
catch (Exception ex)
{
throw;
}
var bundleId = BinaryBundleClient.Create(BinaryBundle);
patient.Identifier.Add(new Identifier("BinaryBundle", bundleId.Id));
return BinaryBundleClient.Update(patient);
}
The string[] of pdfForms is base64 and for each form I am creating a new binary and adding data and content type. But the line var binaryResource = BinaryBundleClient.Create(BinaryData); throws an error and data is not a valid json. I tried with different content type but that is not working. Any ideas why?
Assuming you are creating a new resource instance in BinaryBundleClient.Create(BinaryData) and the server to store it.
In your case, you directly pass the binary information in Fhirclient.Create(your data)
binaryResource = BinaryBundleClient.Create(BinaryData);
You must mention the type of the resource instance which follows:
Create Fhir client
var client = new FhirClient("http://server.fire.ly");
After Creating FhirClient You have to create a new resource instance. It will be like
var pat = new Patient() { /* set up data */ };
var created_pat = client.Create<Patient>(pat);
this interaction will throw an Exception when things go wrong, in most cases a FhirOperationException. This exception has an Outcome property that contains an OperationOutcome resource, and which you may inspect to find out more information about why the interaction failed. Most FHIR servers will return a human-readable error description in the OperationOutcome to help you out.
Refer here

Can I get element value in selenium?

I want to get a value from one input in selenium. But I need this value in other project test in the same solution. Can I get this value in this case or I need run both test project at the same time to get it?
This is my variable (I have it in a class project)
public static string strNumeroCotizacion;
I get the value here in a test project called "Cotizacion":
Variables_RW.element = Variables_RW.driver.FindElement(By.XPath("//INPUT[#id='numeroCotizacion']"));
Variables_RW.strNumeroCotizacion = Variables_RW.element.GetAttribute("value").ToString();
And I need use it in this case in other project called "facturacion" in the same solution:
Variables_RW.driver.FindElement(By.XPath("//INPUT[#id='sCotizacion']")).SendKeys("strNumeroCotizacion");
Variables_RW.driver.FindElement(By.XPath("//INPUT[#id='sCotizacion']")).SendKeys(Keys.Enter);
Interesting question. I don't think you can use variable from the different projects.
But you can write the value of that variable in the file when running your project1 and after you can read it in project 2.
It depends on which language you are using in selenium.
This is the Java Solution
To write to the file:
#SuppressWarnings("unchecked")
public void customerDataWrite(String custID, String OrderNum, String Contact) {
// First OrderData
JSONObject createdOrderData = new JSONObject();
createdOrderData.put("customer", custID);
createdOrderData.put("orderName", OrderNum);
createdOrderData.put("contactName", Contact);
// Add order numbers to list
JSONArray OrderDataList = new JSONArray();
OrderDataList.add(createdOrderData);
// Write JSON file
try (FileWriter file = new FileWriter("orderdata.json")) {
file.write(OrderDataList.toJSONString());
file.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
To read from the file:
JSONParser parser = new JSONParser();
try {
Object obj = parser.parse(new FileReader("orderdata.json"));
// Get order object
JSONArray array = (JSONArray) obj;
JSONObject jsonObject = (JSONObject) array.get(0);
// Get order contact name
orderContactName = (String) jsonObject.get("contactName");
System.out.println(orderContactName);
// Get company name
orderCustomerName = (String) jsonObject.get("customer");
System.out.println(orderCustomerName);
// Get order Order name
orderOrderName = (String) jsonObject.get("orderName");
System.out.println(orderOrderName);
}

System.Text.Json.JsonException: The JSON value could not be converted

I'm using Ubuntu and dotnet 3.1, running vscode's c# extension.
I need to create a List from a JSON file, my controller will do some calculations with this model List that I will pass to it
So, here is my code and the error I'm getting.
First, I thought my error was because at model my attributes were char and C#, for what I saw, cannot interpret double-quotes for char, it should be single quotes. Before losing time removing it, I just changed my type declarations to strings and it's the same error.
Can someone help me?
ElevadorModel
using System.Collections.Generic;
namespace Bla
{
public class ElevadorModel
{
public int andar { get; set; }
public string elevador { get; set; }
public string turno { get; set; }
}
}
Program.cs:
class Program
{
static void Main(string[] args)
{
var path = "../input.json";
string jsonString;
ElevadorModel elevadoresModel = new ElevadorModel();
jsonString = File.ReadAllText(path); //GetType().Name = String
Console.WriteLine(jsonString); //WORKS
elevadoresModel = JsonSerializer.Deserialize<ElevadorModel>(jsonString);
}
JSON:
Your input json has an array as the base token, whereas you're expecting an object. You need to change your deserialization to an array of objects.
var elevadoresModels = JsonSerializer.Deserialize<List<ElevadorModel>>(jsonString);
elevadoresModel = elavoresModels.First();
Your input JSON is an array of models, however you're trying to deserialize it to a single model.
var models = JsonSerializer.Deserialize<List<ElevadorModel>>(jsonString);
This is also a problem in Blazor-Client side. For those calling a single object
e.g ClassName = await Http.GetFromJsonAsync<ClassName>($"api/ClassName/{id}");
This will fail to Deserialize. Using the same System.Text.Json it can be done by:
List<ClassName> ListName = await Http.GetFromJsonAsync<List<ClassName>>($"api/ClassName/{id}");
You can use an array or a list. For some reason System.Text.Json, does not give errors and it is successfully able Deserialize.
To access your object, knowing that it is a single object use:
ListName[0].Property
In your case the latter solution is fine but with the path as the input.
In my case, I was pulling the JSON data to deserialize out of an HTTP response body. It looked like this:
var resp = await _client.GetAsync($"{endpoint}");
var respBody = await resp.Content.ReadAsStringAsync();
var listOfInstances = JsonSerializer.Deserialize<List<modelType>>(respBody);
And the error would show up. Upon further investigation, I found the respBody string had the JSON base object (an array) wrapped in double quotes...something like this:
"[{\"prop\":\"value\"},...]"
So I added
respBody = respBody.Trim('\"');
And the error changed! Now it was pointing to an invalid character '\'.
I changed that line to include
respBody = respBody.Trim('\"').Replace("\\", "");
and it began to deserialize perfectly.
For reference:
var resp = await _client.GetAsync($"{endpoint}");
var respBody = await resp.Content.ReadAsStringAsync();
respBody = respBody.Trim('\"').Replace("\\", "");
var listOfInstances = JsonSerializer.Deserialize<List<modelType>>(respBody);

Adding object to JSON file

I'm creating a software on which I added a profiles feature where the user can create profile to load his informations faster. To store these informations, I'm using a JSON file, which contains as much objects as there are profiles.
Here is the format of the JSON file when a profile is contained (not the actual one, an example) :
{
"Profile-name": {
"form_email": "example#example.com",
//Many other informations...
}
}
Here is the code I'm using to write the JSON and its content :
string json = File.ReadAllText("profiles.json");
dynamic profiles = JsonConvert.DeserializeObject(json);
if (profiles == null)
{
File.WriteAllText(jsonFilePath, "{}");
json = File.ReadAllText(jsonFilePath);
profiles = JsonConvert.DeserializeObject<Dictionary<string, Profile_Name>>(json);
}
profiles.Add(profile_name.Text, new Profile_Name { form_email = form_email.Text });
var newJson = JsonConvert.SerializeObject(profiles, Formatting.Indented);
File.WriteAllText(jsonFilePath, newJson);
profile_tr.Nodes.Add(profile_name.Text, profile_name.Text);
debug_tb.Text += newJson;
But when the profiles.json file is completely empty, the profile is successfully written, but when I'm trying to ADD a profile when another one already exists, I get this error :
The best overloaded method match for 'Newtonsoft.Json.Linq.JObject.Add(string, Newtonsoft.Json.Linq.JToken)' has some invalid arguments on the profiles.Add(); line.
By the way, you can notice that I need to add {} by a non-trivial way in the file if it's empty, maybe it has something to do with the error ?
The expected output would be this JSON file :
{
"Profile-name": {
"form_email": "example#example.com",
//Many other informations...
},
"Second-profile": {
"form_email": "anotherexample#example.com"
//Some other informations...
}
}
Okay so I found by reading my code again, so I just replaced dynamic profiles = JsonConvert.DeserializeObject(json); to dynamic profiles = JsonConvert.DeserializeObject<Dictionary<string, Profile_Name>>(json);.
But it still don't fix the non-trivial way I use to add the {} to my file...
The object the first DeserializeObject method returns is actually a JObject, but below you deserialize it as a Dictionary. You shouldn't be mixing the types, choose either one.
If you use the JObject then to add objects you need to convert them to JObjects:
profiles.Add(profile_name.Text, JObject.FromObject(new Profile_Name { form_email = form_email.Text }));
In both cases, when the profile is null you just need to initialize it:
if (profiles == null)
{
profiles = new JObject(); // or new Dictionary<string, Profile_Name>();
}

Reading CollectionJson content in Web Api Project

I have a project similar(Almost identical) to Conference API project which is taking similar approach to the noted project for returning CollectionJson content. I am having difficulty Setting the Collection property of the ReadDocument (Line 30) as it does not have any setter. I could bypass this problem by doing the following change
public CollectionJsonContent(Collection collection)
{
var serializerSettings = new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore,
Formatting = Newtonsoft.Json.Formatting.Indented,
ContractResolver = new CamelCasePropertyNamesContractResolver()
};
collection.Version = "1.0";
Headers.ContentType = new MediaTypeHeaderValue("application/vnd.collection+json");
using (var writer = new JsonTextWriter(new StreamWriter(_memoryStream)){CloseOutput = false})
{
//var readDocument = new ReadDocument(); {IReadDocument.Collection = collection};
var serializer = JsonSerializer.Create(serializerSettings);
serializer.Serialize(writer,collection);
writer.Flush();
}
_memoryStream.Position = 0;
}
Although above code compiles and to some extent sorts out the problem but then again I will have another problem of not being able to consume the JsonCollection content in my controller unit tests. Consider the following unit test code snippet:
using (var request = CreateRequest())
{
var controller = new TestController(DataService) {Request = request};
var temp = await controller.ListAsync(gridSearchData, sampleSearchData);
if ((temp is NotFoundResult) && (sampleCollection.Any()))
{
Assert.Fail("Controller did not return any result but query did");
}
var json = await temp.ExecuteAsync(cancellationTokenSource);
var readDocument = json.Content.ReadAsAsync<ReadDocument>(new[] {new CollectionJsonFormatter()}, cancellationTokenSource).Result;
}
Since I did not set the collection property of ReadDocument readDocument is always empty and I cant read its content.
How do you asynchronously read the contents of JsonCollection on the client side in WEB API projects?
To get a Clear picture of the approach look at the Conference Web Api
and the authors blog
OK all, this has been fixed. The Collection property is now settable again.
I have just pushed release 0.7.0 with this fix, a major naming refactoring as well as a nice improvement to serialization to not write out empty collections.
Please see the release notes for the changes (especially the naming as the package names and namespaces have changed)
As far as I see from your code, you do not serialize a ReadDocument object, but only a property of it (Collection), and then you try to deserialize that value into a new ReadDocument object.
A sample ReadDocument should serialize like this
"{"Collection": [1,2,3,4,5] }"
But you serialize collection, so you get
"[1,2,3,4,5]"
I recommend a surrogate class for serialization like this
class SerializableReadDocument
{
public Collection Collection { get; set; }
}
and update your serialization code like this
using (var writer = new JsonTextWriter(new StreamWriter(_memoryStream)){CloseOutput = false})
{
var readDocument = new SerializableReadDocument() { Collection = collection };
var serializer = JsonSerializer.Create(serializerSettings);
serializer.Serialize(writer, readDocument);
writer.Flush();
}
But, this will not resolve your problem when you try to deserialize your output since ReadDocument does not have a settable Collection property, deserialization will either fail, or return a ReadDocument object with an empty Collection.
You can use SerializableReadDocument if you like in your unit tests.
I am looking into this and will come up with a solution hopeful this weekend, which will either be to make it a public setter, or make the setter internal and have public ctor that accepts a collection.
Sorry for the difficulty.

Categories

Resources