I need to serialize the following json
{
"searchText": "masktl_TABLE_GetMissingTables",
"$skip": 0,
"$top": 1,
"includeFacets": true
}
I've tried this
string payload = JsonConvert.SerializeObject(new
{
searchText = "masktl_TABLE_GetMissingTables",
$skip = 0,
$top = 1,
includeFacets = true
});
But we can not put $ in the name of a variable. Can anyone please suggest me any other way to serialize the json?
Create a Dictionary<string, object> instead:
var dictionary = new Dictionary<string, object>
{
["searchText"] = "masktl_TABLE_GetMissingTables",
["$skip"] = 0,
["$top"] = 1,
["includeFacets"] = true
};
string payload = JsonConvert.SerializeObject(dictionary);
Alternatively, if you need to do this from more than just the one place, create a class with the relevant properties and use the JsonProperty attribute to specify the name within the JSON.
For example:
public class SearchRequest
{
[JsonProperty("searchText")]
public string SearchText { get; set; }
[JsonProperty("$skip")]
public int Skip { get; set; }
[JsonProperty("$top")]
public int Top { get; set; }
[JsonProperty("includeFacets")]
public bool IncludeFacets { get; set; }
}
var request = new SearchRequest
{
SearchText = "masktl_TABLE_GetMissingTables",
Skip = 0,
Top = 1,
IncludeFacets = true
};
string payload = JsonConvert.SerializeObject(request);
Instead of Anonymous object, have you tried using dictionary,
string payload = JsonConvert.SerializeObject(new Dictionary<string, object>()
{
{ "searchText", "masktl_TABLE_GetMissingTables" },
{ "$skip", 0 },
{ "$top", 1 },
{ "includeFacets", true }
});
Try Online
If you have any defined model class for given json format then you can JsonPropertyAttribute to change the name of property at the time of serialization.
Declare:
public class Pagination
{
[JsonProperty("searchText")]
public string SearchText{ get; set; }
[JsonProperty("$skip")]
public int Skip { get; set; }
[JsonProperty("$top")]
public int Top { get; set; }
[JsonProperty("includeFacets")]
public bool IncludeFacets { get; set; }
}
Usage:
var paginationObj = new Pagination()
{
SearchText = "masktl_TABLE_GetMissingTables",
Skip = 0,
Top = 1,
IncludeFacets = true
};
string payload = JsonConvert.SerializeObject(paginationObj);
Try online
Related
I'm having trouble loading this json object into an array.
Here is a snippet (fragment) of my JSON response from the API:
{
"count":192,
"value":[
{
"id":"03dd9f56-108f-4e8f-b92e-93df05717464",
"name":"IIBTest",
"url":"https://devops.com/tfs/DefaultCollection/_apis/projects/03dd9f56-108f-4e8f-b92e-93df05717464",
"state":"wellFormed",
"revision":14434848,
"visibility":"private",
"lastUpdateTime":"2016-08-19T12:21:37.187Z"
},
{
"id":"b7e15034-fc8f-4f7e-866a-cb06f44b12ed",
"name":"MS Project POC",
"description":"POC for MS Project with TFS",
"url":"https://devops.com/tfs/DefaultCollection/_apis/projects/b7e15034-fc8f-4f7e-866a-cb06f44b12ed",
"state":"wellFormed",
"revision":14434955,
"visibility":"private",
"lastUpdateTime":"2017-10-03T19:31:56.56Z"
},
{
"id":"59e06621-c5f5-4fd1-9c55-1def541b99d9",
"name":"WorkflowReporting",
"url":"https://devops.com/tfs/DefaultCollection/_apis/projects/59e06621-c5f5-4fd1-9c55-1def541b99d9",
"state":"wellFormed",
"revision":14434591,
"visibility":"private",
"lastUpdateTime":"2015-09-11T06:59:12.21Z"
},
{
"id":"78a802f0-5eee-4bcb-bde9-a764e46f56db",
"name":"iSolutions",
"description":"",
"url":"https://devops.com/tfs/DefaultCollection/_apis/projects/78a802f0-5eee-4bcb-bde9-a764e46f56db",
"state":"wellFormed",
"revision":14435476,
"visibility":"private",
"lastUpdateTime":"2021-08-05T17:17:26.193Z"
},
{
"id":"1f20506a-63a5-486a-a857-fec64d7486a6",
"name":"Training",
"description":"MLITS Training and Learning",
"url":"https://devops.com/tfs/DefaultCollection/_apis/projects/1f20506a-63a5-486a-a857-fec64d7486a6",
"state":"wellFormed",
"revision":14435350,
"visibility":"private",
"lastUpdateTime":"2021-04-08T22:48:02.923Z"
},
...
}
And here is my code:
public class Rootobject
{
public int count { get; set; }
public Value[] value { get; set; }
}
public class Value
{
public string id { get; set; }
public string name { get; set; }
public string url { get; set; }
public string state { get; set; }
public int revision { get; set; }
public string visibility { get; set; }
public DateTime lastUpdateTime { get; set; }
public string description { get; set; }
}
static void Main(string[] args)
{
var client = new RestClient("https://devops.americannational.com/tfs/defaultcollection/_apis/projects?$top=300&api-version=5.0")
{
Authenticator = new RestSharp.Authenticators.NtlmAuthenticator()
};
client.Timeout = -1;
var request = new RestRequest(Method.GET);
IRestResponse response = client.Execute(request);
var jsonString = response.Content;
var jo = JObject.Parse(jsonString);
//...
}
I am wanting to load the names of the projects into the Array so that I can later iterate through them. Any help is appreciated, I have tried a few things but not having much luck.
you can use var jo = JsonConvert.DeserializeObject<Rootobject>(jsonString);
and then iterate through jo.value
try this
var jsonDeserialized= JsonConvert.DeserializeObject<Rootobject>(json);
as example how to use it this query returns array of project names
var projectNames= jsonDeserialized.value.Select(v => v.name ).ToArray();
output
["IIBTest","MS Project POC","WorkflowReporting","iSolutions","Training"]
this returns a list of projects
var projects= jsonDeserialized.value.ToList();
How can I set JsonSerializer to not add "\u0022" to string for EventData property? Because I get:
{"Id":5,"CreateDate":"2021-04-21T05:26:30.9817284Z","EventData":"{\u0022Id\u0022:1,\u0022Email\u0022:\u0022test#test.test\u0022}"}
I will never deserialize EventData, it must be readable. And I want:
{"Id":5,"CreateDate":"2021-04-21T05:26:30.9817284Z","EventData":"{Id:1,Email:test#test.test}"}
My code:
public class EmailSent
{
public int Id { get; set; }
public string Email { get; set; }
}
public class UserCreated
{
public int Id { get; set; }
public DateTime CreateDate { get; set; }
public string EventData { get; set; }
}
var emailSent = new EmailSent
{
Id = 1,
Email = "test#test.test"
};
var userCreated = new UserCreated
{
Id = 5,
CreateDate = DateTime.UtcNow,
EventData = JsonSerializer.Serialize(emailSent) // I will never deserialize it
};
string result = JsonSerializer.Serialize(userCreated);
You can use, for example, UnsafeRelaxedJsonEscaping:
var serializeOptions = new JsonSerializerOptions
{
WriteIndented = true,
Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
};
string json = JsonSerializer.Serialize(userCreated, serializeOptions);
This will produce the following output:
{
"Id": 5,
"CreateDate": "2021-04-21T07:49:23.4378969Z",
"EventData": "{\"Id\":1,\"Email\":\"test#test.test\"}"
}
Reference: How to customize character encoding with System.Text.Json. Please read the caution there:
Caution
Compared to the default encoder, the UnsafeRelaxedJsonEscaping encoder is more permissive about allowing characters to pass through unescaped:
(...)
This happens because JsonSerializer.Serialize() is invoked more than once.
You can specify 'JSONSerializerOptions' Encoder equal to JavaScriptTenCoder. Create(new TextEncoderSettings(UnicodeRanges.All))
like this
public static string ToString(this object str)
{
try
{
string sResult = JsonSerializer.Serialize(str, new JsonSerializerOptions{WriteIndented = true, Encoder = JavaScriptEncoder.Create(new TextEncoderSettings(System.Text.Unicode.UnicodeRanges.All))});
return sResult;
}
}
I have almost the exact same problem, only my UserCreated is being returned by ASP.NET controller function, I don't directly control serialization.
The simplest solution is to change the type of EventData to JsonNode.
To set EventData from whatever complex object you want, you can use this awkward construct
EventData = JsonNode.Parse(JsonSerializer.Serialize(complexData))
Complete minimal example:
[Test]
public void Test1()
{
Dictionary<string, string> complexData =
new Dictionary<string, string>() { { "A", "B" } };
NestedJason toSerialize = new NestedJason()
{
FormName = "String",
FormData = JsonNode.Parse(JsonSerializer.Serialize(complexData))
};
Console.WriteLine(JsonSerializer.Serialize(toSerialize));
// prints {"FormName":"String","FormData":{"A":"B"}}
}
}
public class NestedJason
{
public string FormName { get; set; }
public JsonNode FormData { get; set; }
}
A cleaner option is to make FormData type object. (I'm assuming you don't want to make it type EmailSent because you want to store random data about many different types of events.) If you round trip the EventData as object, it will go in as EmailSent and come back out as JsonElement. Manual steps would be required to get it back to an EmailSent.
public class Tests
{
[Test]
public void Test1()
{
Dictionary<string, string> complexData =
new Dictionary<string, string>() { { "A", "B" } };
NestedJason toSerialize = new NestedJason()
{
FormName = "Sting",
FormData = complexData
};
Console.WriteLine(JsonSerializer.Serialize(toSerialize));
NestedJason result = JsonSerializer.Deserialize(
JsonSerializer.Serialize(toSerialize),
typeof(NestedJason)) as NestedJason;
Console.WriteLine(result.FormData.GetType().Name);
}
}
public class NestedJason
{
public string FormName { get; set; }
public Object FormData { get; set; }
}
(I personally will be using the previous JsonNode option, that is more editable, but the object option skips that round trip serialization kludge.)
I have class object and I need to store its values and keys in specific format.
public class AppSettings
{
public int TokenLifeTime { get; set; } = 450;
public List<string> Urls { get; set; } = new List<string>
{
"www.google.com",
"www.hotmail.com"
};
public List<ServersList> ServersList { get; set; } = new List<ServersList>
{
new ServersList {IsHttpsAllowed = false},
new ServersList {IsHttpsAllowed = true}
};
}
public class ServersList
{
public bool IsHttpsAllowed { get; set; }
}
I want to get keys in this format.
"AppSettings:TokenLifeTime" , 450
"AppSettings:Urls:0", "www.google.com"
"AppSettings:Urls:1", "www.hotmail.com"
"AppSettings:ServersList:0:IsHttpsAllowed", false
"AppSettings:ServersList:1:IsHttpsAllowed", true
Is there any way to get all keys as string recursively regardless of object depths. Above code is just an example in real case I have long list and lot more data.
I don't think that there is anything out of the box for this.
You would need to create something yourself and define your rules.
In its more primitive form, I'd start with this:
Type t = typeof(AppSettings);
Console.WriteLine("The {0} type has the following properties: ",
t.Name);
foreach (var prop in t.GetProperties())
Console.WriteLine(" {0} ({1})", prop.Name,
prop.PropertyType.Name);
Then add a rule for IEnumerable to handle them in iterations and so forth for objects and primitive value types.
I have a couple of examples for you:
Option 1:
public class AppSettings
{
public int TokenLifeTime { get; set; } = 450;
public Dictionary<string, ServersList> Urls { get; set; } = new Dictionary<string, ServersList>
{
{"www.google.com", new ServersList {IsHttpsAllowed = false}},
{ "www.hotmail.com", new ServersList {IsHttpsAllowed = true}}
};
}
public class ServersList
{
public bool IsHttpsAllowed { get; set; }
}
This option would group the values together but you would lose 'int' based index. Not sure if that is important.
Option 2:
public class AppSettings
{
public int TokenLifeTime { get; set; } = 450;
public List<KeyValuePair<string, ServersList>> Urls { get; set; } = new List<KeyValuePair<string, ServersList>>
{
new KeyValuePair<string, ServersList>("www.google.com",new ServersList {IsHttpsAllowed = false}),
new KeyValuePair<string, ServersList>("www.hotmail.com", new ServersList {IsHttpsAllowed = true})
};
public List<ServersList> ServersList { get; set; } = new List<ServersList>
{
new ServersList {IsHttpsAllowed = false},
new ServersList {IsHttpsAllowed = true}
};
}
public class ServersList
{
public bool IsHttpsAllowed { get; set; }
}
This option will retain 'int' based indexing and the values are still grouped. But feels clunky...
Option 3: (the one I would go with)
public class AppSettings
{
public int TokenLifeTime { get; set; } = 450;
public List<Server> ServersList { get; set; } = new List<Server>
{
new Server { Url = "www.google.com", IsHttpsAllowed = false},
new Server { Url = "www.hotmail.com", IsHttpsAllowed = true}
};
}
public class Server
{
public string Url { get; set; }
public bool IsHttpsAllowed { get; set; }
}
This option still gives you 'int' based indexing and it groups the data together (as it should be from what I understand in the example).
I am trying to create a log file in json format from a List.
my class for list is
public class ChunkItem
{
public int start { get; set; }
public int end { get; set; }
}
public class DownloadItem
{
public int id { get; set; }
public string fname { get; set; }
public string downloadPath { get; set; }
public int chunkCount { get; set; }
public ChunkItem[] chunks { get; set; }
public DownloadItem(int _id, string _fname, string _downloadPath, int _chunkCount, ChunkItem[] _chunks)
{
id = _id;
fname = _fname;
downloadPath = _downloadPath;
chunkCount = _chunkCount;
chunks = _chunks;
}
}
creating a json file from this class works fine
ChunkItem[] chunks = new ChunkItem[2];
chunks[0] = new ChunkItem();
chunks[0].start = 0;
chunks[0].end = 0;
chunks[1] = new ChunkItem();
chunks[1].start = 0;
chunks[1].end = 0;
List<DownloadItem> lst = new List<DownloadItem>();
lst.Add(new DownloadItem(0, "", "", 2, chunks));
lst.Add(new DownloadItem(1, "aaa", "sss", 2, chunks));
lst.Add(new DownloadItem(2, "bbb", "ddd", 2, chunks));
string json = JsonConvert.SerializeObject(lst);
System.IO.File.WriteAllText(logPath, json);
I want to read the file to same class list and do some updates or add new lines
I can read the file to a string but cannot create a new list
how can I convert string (read json file) to List<DownloadItem> new list
You need to read all the contends from the file and deserialize the json string to List<DownloadItem>
var jsonData = File.ReadAllText(filePath)
var list = JsonConvert.DeserializeObject<List<DownloadItem>>(jsonData);
Clas DownloadItem is missing a default parameterless constructor.
I use Newtonsoft, where creating the instances and filling them is simple
var result = Newtonsoft.Json.JsonConvert.DeserializeObject<MyClass>(jsonString);
I am attempting to use the Newtonsoft JSON library to parse a JSON string dynamically using C#. In the JSON is a named array. I would like to remove the square brackets from this array and then write out the modified JSON.
The JSON now looks like the following. I would like to remove the square bracket from the ProductDescription array.
{
"Product": "123",
"to_Description": [
{
"ProductDescription": "Product 1"
}
]
}
Desired result
{
"Product": "123",
"to_Description":
{
"ProductDescription": "Product 1"
}
}
I believe I can use the code below to parse the JSON. I just need some help with making the modification.
JObject o1 = JObject.Parse(File.ReadAllText(#"output.json"));
The to_Description property starts off as List<Dictionary<string,string>> and you want to take the first element from the List.
So, given 2 classes
public class Source
{
public string Product {get;set;}
public List<Dictionary<string,string>> To_Description{get;set;}
}
public class Destination
{
public string Product {get;set;}
public Dictionary<string,string> To_Description{get;set;}
}
You could do it like this:
var src = JsonConvert.DeserializeObject<Source>(jsonString);
var dest = new Destination
{
Product = src.Product,
To_Description = src.To_Description[0]
};
var newJson = JsonConvert.SerializeObject(dest);
Note: You might want to check there really is just 1 item in the list!
Live example: https://dotnetfiddle.net/vxqumd
You do not need to create classes for this task. You can modify your object like this:
// Load the JSON from a file into a JObject
JObject o1 = JObject.Parse(File.ReadAllText(#"output.json"));
// Get the desired property whose value is to be replaced
var prop = o1.Property("to_Description");
// Replace the property value with the first child JObject of the existing value
prop.Value = prop.Value.Children<JObject>().FirstOrDefault();
// write the changed JSON back to the original file
File.WriteAllText(#"output.json", o1.ToString());
Fiddle: https://dotnetfiddle.net/M83zv3
I have used json2csharp to convert the actual and desired output to classes and manipulated the input json.. this will help in the maintenance in future
First defined the model
public class ToDescription
{
public string ProductDescription { get; set; }
}
public class ActualObject
{
public string Product { get; set; }
public List<ToDescription> to_Description { get; set; }
}
public class ChangedObject
{
public string Product { get; set; }
public ToDescription to_Description { get; set; }
}
Inject the logic
static void Main(string[] args)
{
string json = "{\"Product\": \"123\", \"to_Description\": [ { \"ProductDescription\": \"Product 1\" } ]} ";
ActualObject actualObject = JsonConvert.DeserializeObject<ActualObject>(json);
ChangedObject changedObject = new ChangedObject();
changedObject.Product = actualObject.Product;
changedObject.to_Description = actualObject.to_Description[0];
string formattedjson = JsonConvert.SerializeObject(changedObject);
Console.WriteLine(formattedjson);
}
Why not:
public class EntityDescription
{
public string ProductDescription { get; set; }
}
public class Entity
{
public string Product { get; set; }
}
public class Source : Entity
{
[JsonProperty("to_Description")]
public EntityDescription[] Description { get; set; }
}
public class Target : Entity
{
[JsonProperty("to_Description")]
public EntityDescription Description { get; set; }
}
var raw = File.ReadAllText(#"output.json");
var source = JsonConvert.DeserializeObject<Source>(raw);
var target = new Target { Product = source.Product, Description = source.Description.FirstOrDefault() };
var rawResult = JsonConvert.SerializeObject(target);
Update For dynamic JSON
var jObject = JObject.Parse(File.ReadAllText(#"output.json"));
var newjObject = new JObject();
foreach(var jToken in jObject) {
if(jToken.Value is JArray) {
List<JToken> l = jToken.Value.ToObject<List<JToken>>();
if(l != null && l.Count > 0) {
newjObject.Add(jToken.Key, l.First());
}
} else {
newjObject.Add(jToken.Key, jToken.Value);
}
}
var newTxt = newjObject.ToString();