I catch a JSON with .NET:
string result = json_serializer.Deserialize(myJSON);
well the structure of JSON is such as:
result
data[0]
user
bio
name
nickname
data[1]
user
bio
name
nickname
data[2]
user
bio
name
nickname
and I'd like to get only the first nickname (as string) that have some value: I mean, it is not null and is not empty.
How can I do it?
From what I understand from your question, you would want something like this,
public string FirstUserNickname(string JsonUserInfo)
{
JavaScriptSerializer JsonSerializer = new JavaScriptSerializer();
ResultData Results = JsonSerializer.Deserialize<ResultData>(JsonUserInfo);
foreach (UserInfo UserInfo in Results.result)
{
if (string.IsNullOrEmpty(UserInfo.nickname))
return UserInfo.nickname;
}
return null;
}
public class ResultData
{
public List<UserInfo> result;
}
public class UserInfo
{
public string bio;
public string name;
public string nickname;
}
This will achieve your goal and is a strongly typed approach, using the JavaScriptSerializer class from the System.Web.Extensions assembly, more info can be found here.
You can use Linq to JSON (search NuGet for Newtonsoft Json). Assume your JSON looks like:
{ "result": [ { "bio": "foo", "name": "Robin", "nickname": "Moll" },
{ "bio": "bar", "name": "Ted", "nickname": "DoctorZ" },
{ "bio": "moo", "name": "Barney", "nickname": "Wait4it" } ]
}
Then getting name of first user:
JObject jo = JObject.Parse(json);
var name = (string)jo["result"][0]["name"]; // Robin
Of course if it is possible that you will not have any users, then you should verify that user exists:
JObject jo = JObject.Parse(json);
var user = jo["result"].FirstOrDefault();
if (user != null)
name = (string)user["name"];
Using Linq to JSON you can deserialize to .net objects, like so:
Result deserializedResult = JsonConvert.DeserializeObject<Result>(json);
After that you can use LINQ to query the objects:
User nicknameduser = deserializedResult.Users
.FirstOrDefault(r => !string.IsNullOrEmpty(r.nickname))
if (nicknameduser == null) return null;
return nicknameduser.nickname;
Related
I created a database with JSON columns in mysql.
API defined in Swagger.
Writing JSON to the database works without problems, but when reading, the value of the JSON field is shown as an escaped string and not JSON
Here is part of model:
/// <summary>
/// Gets or Sets Doc
/// </summary>
[DataMember(Name="doc")]
public Dictionary<string, string> Doc { get; set; }
I also tried with string type and Dictionary<string, object> but unsuccessful.
Get method is here:
public virtual IActionResult GetDataById([FromRoute][Required]int? dataId, [FromRoute][Required]string jsonNode)
{
if(_context.Data.Any( a => a.Id == dataId)) {
var dataSingle = _context.Data.SingleOrDefault( data => data.Id == dataId);
return StatusCode(200, dataSingle);
} else {
return StatusCode(404);
}
}
}
And resulting JSON resposne looks like this one:
{
"field1": "value1",
"field2": "value2",
"doc": "{\"key1\":\"value1\",\"key2\":\"value2\",\"key3\":{\"subkey3-1\":\"value3-1\",\"subkey3-2\":\"value3-2\"}}"
}
but correct JOSN should be linke this one:
{
"field1": "value1",
"field2": "value2",
"doc": {
"key1":"value1",
"key2":"value2",
"key3":{
"subkey3-1":"value3-1",
"subkey3-2":"value3-2"
}
}
}
If I try to return just "Doc" (JSON) field, response JSON is properly formatted.
I tried different serialization/deserialization but unsuccessful.
If I have public Dictionary<string, string> Doc { get; set; } in Model I got error:
fail: Microsoft.AspNetCore.Server.Kestrel[13]
Connection id "0HM1VN0F0I0IM", Request id "0HM1VN0F0I0IM:00000001": An unhandled exception was thrown by the application.
System.InvalidOperationException: The property 'Data.Doc' is of type 'Dictionary<string, string>' which is not supported by current database provider. Either change the property CLR type or ignore the property using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'
and for public string Doc { get; set; } in Model I got "doc" field value as escaped string as I mention above.
What would be the best way to go about this?
A few days later I found a resolution.
You need a one helper method that converts a string to object, exactly JObject if you use Json.NET - Newtonsoft.
public static JObject getJsonOutOfData (dynamic selectedData)
{
var data = JsonConvert.SerializeObject(selectedData);
var jsonData = (JObject)JsonConvert.DeserializeObject<JObject>(data);
if (selectedData.Doc != null) {
JObject doc = JObject.Parse(selectedData.Doc);
JObject docNode = JObject.Parse("{\"doc\":" + doc.ToString() + "}");
var jsonDoc = (JObject)JsonConvert.DeserializeObject<JObject>(docNode.ToString());
jsonData.Property("doc").Remove();
jsonData.Merge(jsonDoc, new JsonMergeSettings
{
MergeArrayHandling = MergeArrayHandling.Union
});
}
return jsonData;
}
and call it in the IActionResult method
public virtual IActionResult GetDataById([FromRoute][Required]int? accidentId, [FromRoute][Required]string jsonNode)
{
if (_context.Data.Any( a => a.Id == accidentId)) {
var accidentSingle = _context.Data.SingleOrDefault( accident => accident.Id == accidentId);
var result = getJsonOutOfData(accidentSingle);
return StatusCode(200, result.ToString());
} else {
return StatusCode(404);
}
}
In order to use unescaped JSON in POST/PUT requests, you should have a string type as a property type of JSON filed in the database model, and create an additional "request" model and set JSON property as "Object" type:
Database Model:
[DataMember(Name="doc")]
public string Doc { get; set; }
Request Model:
[DataMember(Name="doc")]
public Object Doc { get; set; }
For example Create model looks like:
public virtual IActionResult CreateData([FromBody]DataCreateRequest body)
{
var accidentObject = new Data() {
ColumnOne = body.ColumnOne,
ColumnTwo = body.ColumnTwo,
ColumnThree = body.ColumnThree,
Doc = (bodyDoc != null) ? body.Doc.ToString() : "{}"
};
_context.Data.Add(accidentObject);
_context.SaveChanges();
return StatusCode(200, getJsonOutOfData(accidentObject));
}
Say I have some JSON
{
"name": "John"
... other properties
}
It could also be like
{
"person": {
"name": "John"
}
... other properties
}
And this code to look for the name field.
var obj = JObject.Parse(json);
var token = obj.SelectToken("$..name");
token = "James";
After getting it, I want to set it to another value and put it back into the JSON to get
{
"person": {
"name": "James"
}
... other properties
}
or
{
"person": {
"name": "James"
}
... other properties
}
How can I put the JToken back into the JObject?
Please try this:
var o = JObject.Parse(json);
o["person"]["name"] = "James";
var backToJson = o.ToString(Formatting.None);
Let's say I have this example JSON:
"Test": {
"KIf42N7OJIke57Dj6dkh": {
"name": "test 1"
},
"xsQMe4WWMu19qdULspve": {
"name": "test 2"
}
}
I want to parse this into an Array of a custom class I have, which will be exampled below:
class Class1 {
public string Name { get; set; }
Class1(string name) {
Name = name;
}
}
How can I parse this using Json.NET's JObject.Parse?
You can achieve your goal with JPath query like this :
var myArray = JObject
.Parse(json)
.SelectTokens("$.Test..name")
.Values<string>()
.Select(s => new Class1(s))
.ToArray();
But probably not the best way to do it.
I personnaly prefere to create classes to represent the json structure and then apply transformations.
void Main()
{
var json = #"{""Test"": {
""KIf42N7OJIke57Dj6dkh"": {
""name"": ""test 1""
},
""xsQMe4WWMu19qdULspve"": {
""name"": ""test 2""
}
}
}";
var root = JsonConvert.DeserializeObject<Root>(json);
var array = root.Test.Select(i => i.Value).ToArray();
array.Dump();
}
public class Root
{
public Dictionary<string, Class1> Test { get; set; }
}
public class Class1
{
public string Name { get; set; }
public Class1(string name)
{
Name = name;
}
}
To begin with, your Json is missing starting/closing braces. The Json needs to have wrapping braces around the Test value.
{
'Test':
{
'KIf42N7OJIke57Dj6dkh': {'name': 'test 1'},
'xsQMe4WWMu19qdULspve': {'name': 'test 2'}
}
}
If you are missing it in the original Json, you could wrap the current input Json as following.
var correctedJson = $"{{{inputJsonString}}}";
If you want to parse the Json Objects to Array of Class1 without creating additional concrete data structures and using JPath Queries, you could use Anonymous Types for the purpose using the DeserializeAnonymousType Method proved by Json.Net. For example,
var sampleObject = new {Test = new Dictionary<string,Class1>()};
var data = JsonConvert.DeserializeAnonymousType(correctedJson,sampleObject);
var result = data.Test.Select(x=>x.Value).ToArray();
You could also achieve it using JPath Query or creating Concrete Data Structures as #Kalten as described in his answer.
Can somebody help me to parse the json and get the details.
Lets say i have Top2 input parameter as Police and i want to know the respective Top3 and in that Top3 array i need to check whether Test1Child value is there or not.
I am using newtonsoft json + c# and so far i can get till DeviceTypes using below code
var json = File.ReadAllText(jsonFile); // below json is stored in file jsonFile
var jObject = JObject.Parse(json);
JArray MappingArray =(JArray)jObject["Top1"];
string strTop1 = ObjZone.Top1.ToString();
string strTop2 = ObjZone.Top2.ToString();
var JToken = MappingArray.Where(obj => obj["Top2"].Value<string>() == strTop2).ToList();
//Json
{
"Top1": [
{
"Top2": "Test1",
"Top3": [
"Test1Child"
]
},
{
"Top2": "Test2",
"Top3": [
"Test2Child"
]
}
]
}
I'd use http://json2csharp.com/ (or any other json to c# parser) and then use C# objects (it's just easier for me)
This would look like that for this case:
namespace jsonTests
{
public class DeviceTypeWithResponseTypeMapper
{
public string DeviceType { get; set; }
public List<string> ResponseTypes { get; set; }
}
public class RootObject
{
public List<DeviceTypeWithResponseTypeMapper> DeviceTypeWithResponseTypeMapper { get; set; }
}
}
and the use it like that in code:
var rootob = Newtonsoft.Json.JsonConvert.DeserializeObject<RootObject>(str);
var thoseThatHaveNotUsed = rootob.DeviceTypeWithResponseTypeMapper.Where(dtwrtm =>
dtwrtm.ResponseTypes.Any(rt => rt == "NotUsed"));
foreach (var one in thoseThatHaveNotUsed)
{
Console.WriteLine(one.DeviceType);
}
this code lists all the Device types that have "NotUsed" among the responses.
version 2 (extending your code) would look like that, i believe:
static void Main(string[] args)
{
var json = str; // below json is stored in file jsonFile
var jObject = JObject.Parse(json);
JArray ZoneMappingArray = (JArray)jObject["DeviceTypeWithResponseTypeMapper"];
string strDeviceType = "Police";
string strResponseType = "NotUsed";
var JToken = ZoneMappingArray.Where(obj => obj["DeviceType"].Value<string>() == strDeviceType).ToList();
var isrespTypeThere = JToken[0].Last().Values().Any(x => x.Value<string>() == strResponseType);
Console.WriteLine($"Does {strDeviceType} have response type with value {strResponseType}? {yesorno(isrespTypeThere)}");
}
private static object yesorno(bool isrespTypeThere)
{
if (isrespTypeThere)
{
return "yes!";
}
else
{
return "no :(";
}
}
result:
and if you'd like to list all devices that have response type equal to wanted you can use this code:
var allWithResponseType = ZoneMappingArray.Where(jt => jt.Last().Values().Any(x => x.Value<string>() == strResponseType));
foreach (var item in allWithResponseType)
{
Console.WriteLine(item["DeviceType"].Value<string>());
}
I am trying to print values from a Json string in a gridview with C# using Visual Studio 2017. The problem is that I can't get the specific Value to a single word.
Here is my code:
string link = #"http://alexander.*************/test.php";
string json = new WebClient().DownloadString(link);
JObject jObject = JObject.Parse(json);
I want to print both Values from "Name" in the gridview, but how?
The Names has to put in this Item list:
myItems = (array?);
string test2 = test1.ToString(Formatting.Indented);
ArrayAdapter<string> adapter = new ArrayAdapter<string>(this, Android.Resource.Layout.SimpleListItem1, myItems);
GridviewCoins.Adapter = adapter;
And finally the json string is:
{
"Coins": [[{
"Name": "007",
"Id": "5294",
}], [{
"Name": "1337",
"Id": "20824",
}
There is a couple problems here, first is that your Coins Property is an array of arrays, and that you jsonObject is not complete it should look like :
"{ "Coins": [[{ "Name": "007", "Id": "5294", } ], [{ "Name": "1337", "Id": "20824", }]]}";
That said if this is a copy paste error I would do some thing like:
public IEnumerable<Coin> GetCoins(string json)
{
var jObject = JObject.Parse(json);
var coinPropery = jObject["Coins"] as JArray;
var coins = new List<Coin>();
foreach (var property in coinPropery)
{
var propertyList = JsonConvert.DeserializeObject<List<Coin>>(property.ToString());
coins.AddRange(propertyList);
}
return coins;
}
and the coin object:
public class Coin
{
public int Id { get; set; }
public string Name { get; set; }
}
when then you have a c# object and you can do what ever you want with it.
EDIT:
You can add to gridview by following Click here