Newtonsoft.Json.JsonConvert.SerializeObject single item vs multiple item - c#

Found out that serialize XML object with single item and multiple item gives me different format, thus accessing it would be different.
For example, with single item:
{
"schemalist": {
"schema": {
"fieldid": "email",
"displayname": "email",
}
}
}
and
{
"schemalist": {
"schema": [
{
"fieldid": "name",
"displayname": "name",
},
{
"fieldid": "email",
"displayname": "email",
}
]
}
}
so when I parse them jQuery.ParseJSON, I have to access them differently
schemalist.schema.fieldid
and
schemalist.schema[0].fieldid
is there a way to convert to json even with single item, so I can use
schemalist.schema[0].fieldid even across single, multiple items?
thanks!
Edit:
Here's my xml input:
<schemalist>
<schema>
<fieldid><![CDATA[name]]></fieldid>
<displayname><![CDATA[name]]></displayname>
</schema>
<schema>
<fieldid><![CDATA[email]]></fieldid>
<displayname><![CDATA[email]]></displayname>
</schema>
but sometimes the return could have only one schema:
<schemalist>
<schema>
<fieldid><![CDATA[email]]></fieldid>
<displayname><![CDATA[email]]></displayname>
</schema>
</schemalist>
then I would do my conversion like this:
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
return Newtonsoft.Json.JsonConvert.SerializeObject(doc);

well, what i end up doing was to remove the property and then add it again.
// run the code below with $(schemalist.schemalist.schema).length == 1
// create a schema array
var schema = [];
schema.push(schemalist.schemalist.schema);
// delete the property
delete schemalist.schemalist.schema;
schemalist['schema'] = schema;
so instead of accessing properties fieldid:
schemalist.schema.fieldid,
I can use
schemalist.schema[i].fieldid
even with one element, ha!

Related

How to convert json key with an underscore to a new object in C#

If I have some json such like..
{
"name": "test",
"dob": "20010101",
"tel_home": "01785200200",
"tel_work": "01785300300",
"tel_mobile": "07123456789",
. . .
}
How can I convert it to (whenever an underscore is shown)
{
"name": "test",
"dob": "20010101",
"tel": {
"home": "01785200200",
"work": "01785300300",
"mobile": "07123412345"
}
. . .
}
The properties can change so I cannot deserialise to an object.
Many thanks for any help
-Jenny
You can parse your JSON into JObject, save all properties, starting from tel_ value. Then remove them from original JObject, create a new one with updated properties names and finally add the created object to original one
var json = JObject.Parse(jsonString);
var properties = json.Properties()
.Where(p => p.Name.StartsWith("tel_"))
.ToList();
properties.ForEach(p => json.Remove(p.Name));
var newObject = new JObject(properties.Select(p => new JProperty(p.Name.Replace("tel_", string.Empty), p.Value)));
json.Add("tel", newObject);
Console.WriteLine(json);
It gives you the following result
{
"name": "test",
"dob": "20010101",
"tel": {
"home": "01785200200",
"work": "01785300300",
"mobile": "07123456789"
}
}
With Newtonsoft you can declare custom serialzers:
https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_JsonSerializer.htm
This will allow you to inspect one token at a time and place it any object or variable you want.

Remove property name from Json when its array

I am converting XML to JSON.
Input:
<emp
id="17377"/>
<CustomerList>
<Customer
id="67149"/>
<Customer id="64260"/>
</CustomerList>
OutPut:
"emp": {
"id": "17377"
},
"CustomerList": {
"Customer": [
{
"id": "67149"
},
{
"id": "64260"
}
]
}
But I need the below output. But I can not remove <Customer from <CustomerList> in the input. Also Please note that I need accept dynamic name
of array input. But always i want to remove the inner property name to be removed. in this example its Customer.But I may get MarkList->Mark then I need to remove remove Mark, etc.,:
"emp": {
"id": "17377"
},
"CustomerList": [
{
"id": "67149"
},
{
"id": "64260"
}
]
Is this possible please.
I use below code to convert XML to Json:
var xml = new XmlDocument();
xml.XmlResolver = null;
xml.LoadXml(richTextBox1.Text);
var jsonText = JsonConvert.SerializeXmlNode(xml,Newtonsoft.Json.Formatting.Indented);
Note:
One solution would be find the char "[" and remove before "[" and after "{".
This is not possible, as it is simply trying to change to JSON scheme in which it was orignally built.
what you can do, is use JObject to change the value of customer to feet your needs:
JObject rss = JObject.Parse(json);
JObject customers = rss.SelectToken("CustomerList");
customers ["Customer"] = newValue;
This is the snippet, modify this in your code to feet your needs.

Getting error parsing a Json response from a service c#

I am consuming an api from a .NET project and I am getting a json response, but I can't parse it correctly using Newtonsoft.Json.
I want to get the values like eda50ef6a96442088e88401ffb4846df or 965507aad38245b1b7cc62a397c9af2e. I also checked this json with an online json validator and it says it's wrong. What should I do? Any help?
{
"resp": {
"state": "ok",
"Query": {
"Header": {
"Cell": {
"HeaderName": "Guid",
"Type": "System.Guid"
}
},
"Row": {
"Cell": {
"name": "Guid",
"eda50ef6a96442088e88401ffb4846df"
}
},
"Row": {
"Cell": {
"name": "Guid",
"965507aad38245b1b7cc62a397c9af2e"
}
}
}
}
}
I also put here the response of the service in xml format.
<resp state="ok">
<Query>
<Header>
<Cell>
<HeaderName>Guid</HeaderName>
<Type>System.Guid</Type>
</Cell>
</Header>
<Row>
<Cell name="Guid">eda50ef6a96442088e88401ffb4846df</Cell>
</Row>
<Row>
<Cell name="Guid">965507aad38245b1b7cc62a397c9af2e</Cell>
</Row>
</Query>
</resp>
As others have already pointed out, the "JSON" being produced by this API is definitely invalid as it does not conform to the JSON standard.
I want to address the second part of your question, "What should I do?"
Obviously, if you control the project or API which is producing this JSON, then you should fix it to make it produce valid JSON. Instead of hand-coding the output (which is most likely how this output came to be) you should instead build up objects in memory (using nested dictionaries and lists would be a good choice here) and then serialize them using a proper JSON serializer like Json.Net. The serializer will be able to turn them into correct JSON for you.
If you do NOT control the sproject or API which is producing this JSON, then you should definitely notify the project author that it is producing invalid output and ask them to fix it, if possible.
If the project owner cannot be contacted, or s/he can't or won't fix it, or if you don't have time to wait for a proper fix, then you should switch to using the XML version instead. This looks to be correctly formatted and you should be able to consume this without any trouble using standard XML classes like LINQ-to-XML.
If you absolutely must have JSON to work with, for whatever reason, then you can try using Json.Net to convert the XML response directly into JSON using JsonConvert.SerializeXNode:
string json = JsonConvert.SerializeXNode(XElement.Parse(xml), Formatting.Indented);
However, there are some potential pitfalls with this approach, notably that the conversion process can produce different JSON depending on the number of nodes in the XML. See Converting between JSON and XML for more information.
With the XML shown in your question, SerializeXNode would produce this JSON:
{
"resp": {
"#state": "ok",
"Query": {
"Header": {
"Cell": {
"HeaderName": "Guid",
"Type": "System.Guid"
}
},
"Row": [
{
"Cell": {
"#name": "Guid",
"#text": "eda50ef6a96442088e88401ffb4846df"
}
},
{
"Cell": {
"#name": "Guid",
"#text": "965507aad38245b1b7cc62a397c9af2e"
}
}
]
}
}
}
It looks like the JSON is malformed to me... particularly here:
"Row": {
"Cell": {
"name": "Guid",
"eda50ef6a96442088e88401ffb4846df"
}
Note that the string you want to get has no "Key" name. So the Cell Key has a value which is a JSON object with a name Key (whose value is "Guid"), but the long string has no key name.
It should have a key for that value, something like this:
"Row": {
"Cell": {
"name": "Guid",
"value": "eda50ef6a96442088e88401ffb4846df"
}
For the JSON to be valid, it needs to consist of key/value pairs.

Is there any way of parsing a JSON string without deserialising it?

I am calling a web service that returns JSON with a duplicate node in some circumstances, providing output similar to this:
{
"shipments": [
{
"id": "A000001",
"name": "20141208 140652",
"type": "OUTLET",
"date": "2014-12-08 14:06:52",
"status": "SENT",
"received_at": null,
"created_at": "2014-12-08 14:06:52",
"updated_at": null,
"outlet_id": "SH000064"
},
{
"id": "A000002",
"name": "20141204 122650",
"type": "SUPPLIER",
"date": "2014-12-04 12:26:50",
"outlet_id": "SH000064",
"supplier_id": null,
"status": "RECEIVED",
"outlet_id": "SH000064",
"received_at": "2014-12-04 12:28:43",
"created_at": "2014-12-04 12:26:50",
"updated_at": "2014-12-04 12:28:43"
}
]
}
I am dependent on the provider of the service to fix this and this is not a priority for them so I have to deal with it. To handle this I am converting the JSON to XML, using the JsonReaderWriterFactory, and then removing the duplicate nodes from the resulting XML using the following routine:
protected virtual void RemoveDuplicateChildren(XmlNode node)
{
if (node.NodeType != XmlNodeType.Element || !node.HasChildNodes)
{
return;
}
var xNode = XElement.Load(node.CreateNavigator().ReadSubtree());
var duplicateNames = new List<string>();
foreach (XmlNode child in node.ChildNodes)
{
var isBottom = this.IsBottomElement(child); // Has no XmlNodeType.Element type children
if (!isBottom)
{
this.RemoveDuplicateChildren(child);
}
else
{
var count = xNode.Elements(child.Name).Count();
if (count > 1 && !duplicateNames.Contains(child.Name))
{
duplicateNames.Add(child.Name);
}
}
}
if (duplicateNames.Count > 0)
{
foreach (var duplicate in duplicateNames)
{
var nodeList = node.SelectNodes(duplicate);
if (nodeList.Count > 1)
{
for (int i=1; i<nodeList.Count; i++)
{
node.RemoveChild(nodeList[i]);
}
}
}
}
}
I now in a separate area need to use the DataContractJsonSerializer to deserialise the JSON to a strongly typed object, using the following code:
DataContractJsonSerializer serialiser = new DataContractJsonSerializer(typeof(ShipmentList));
MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(json));
var result = serialiser.ReadObject(stream);
This fails when the JSON contains that duplicate node, so I need to implement the same functionality as in the RemoveDuplicateChildren method but stepping through the JSON instead of an XML node, before the deserialisation. I can't use the quick-and-dirty option of using JsonConvert to convert to XML, removing the node with my existing method, then converting back to JSON because of the changes in the JSON that will result from the conversion to and from XML. Is there an equivalent way of navigating through a JSON hierarchy in C# as is provided by the XmlNode class?
UPDATE:
This question has become obfuscated by some of the comments. To clarify, the nodes I want to remove from the JSON are any nodes that are a repeat (by name, the content is irrelevant) at the same level of the same parent, such as the second "outlet_id" of the second "shipments" item in the example above. I need to do this in a generic way without hard coded element names. The RemoveDuplicateChildren method above does exactly what is needed, I'm just asking if there is a class I can use to do exactly the same as that method on a JSON string instead of an XML string.

mongodb c# how to work with BSON document

I've spent MANY hours looking for the answer...
This is very easy in PHP but I just can't put it together in C#(I'm new to C# and mongo...)
I'm trying to iterate through all levels of a stored document. The document looks like this:
{
"_id": ObjectId("51f90101853bd88971ecdf27"),
"fields": [
{
"ID": ObjectId("51fd09498b080ee40c00514e"),
"NAME": "ID",
"TYPE": "Text"
},
{
"ID": ObjectId("51fd09a68b080ee40c0064db"),
"NAME": "Title",
"TYPE": "Text"
},
{
"ID": ObjectId("51fd09b28b080ee40c004d31"),
"NAME": "Start Date",
"TYPE": "Date"
},
{
"ID": ObjectId("51fd09c28b080ee40c007f2e"),
"NAME": "Long Description",
"TYPE": "Memo"
}
],
"name": "TODB",
"updated": "Wed Jul 31 2013 08:20:17 GMT-0400 (Eastern Daylight Time)"
}
I have no problem accessing the "name" and "updated" but can't figure out how to access the "fields" array.
Code so far :
{
MongoServer mongo = MongoServer.Create();
mongo.Connect();
var db = mongo.GetDatabase("forms");
mongo.RequestStart(db);
var collection = db.GetCollection("forms");
var query = new QueryDocument("name",
"TODB");
mongo.Disconnect();
}
#foreach(BsonDocument item in collection.Find(query))
{
#item.GetElement("name").Value
#item.GetElement("_id").Value
}
Again, I am able to access the name and _id just not any of the sub document values.
Thanks in advance for any assistance!
After I get the reading figured out, I am also going to want to write data....
There are a few ways, but here's one:
// build some test data
BsonArray dataFields = new BsonArray { new BsonDocument {
{ "ID" , ObjectId.GenerateNewId()}, { "NAME", "ID"}, {"TYPE", "Text"} } };
BsonDocument nested = new BsonDocument {
{ "name", "John Doe" },
{ "fields", dataFields },
{ "address", new BsonDocument {
{ "street", "123 Main St." },
{ "city", "Madison" },
{ "state", "WI" },
{ "zip", 53711}
}
}
};
// grab the address from the document,
// subdocs as a BsonDocument
var address = nested["address"].AsBsonDocument;
Console.WriteLine(address["city"].AsString);
// or, jump straight to the value ...
Console.WriteLine(nested["address"]["city"].AsString);
// loop through the fields array
var allFields = nested["fields"].AsBsonArray ;
foreach (var fields in allFields)
{
// grab a few of the fields:
Console.WriteLine("Name: {0}, Type: {1}",
fields["NAME"].AsString, fields["TYPE"].AsString);
}
You can often use the string indexer ["name-of-property"] to walk through the fields and sub document fields. Then, using the AsXYZ properties to cast the field value to a particular type as shown above.

Categories

Resources