class Program
{
static void Main(string[] args)
{
JSONClass jsonClass = new JSONClass();
JSONElement el = new JSONElement
{
A = 5,
B = "test1"
};
JSONElement el2 = new JSONElement
{
A = 3,
B = "test2"
};
jsonClass.JSONList.Add(el);
jsonClass.JSONList.Add(el2);
var output = JsonSerializer.Serialize<JSONClass>(jsonClass);
Console.WriteLine(output);
}
}
public class JSONClass
{
public List<JSONElement> JSONList = new List<JSONElement>();
}
public class JSONElement
{
public int A { get; set; }
public string B { get; set; }
}
This code returns {} which means that JsonSerializer.Serialize failed to do what it supposed to do. I imagine its because its not smart enough to handle custom types. And here is my question, how to do it. Internet is full of articles how to write custom converters etc, but none of them mention custom types.
Your JSONList member is a public field - whereas JsonSerializer looks for properties.
Change your code for JSONClass to this:
public class JSONClass
{
public List<JSONElement> JSONList { get; } = new List<JSONElement>();
}
The output is then:
{"JSONList":[{"A":5,"B":"test1"},{"A":3,"B":"test2"}]}
The bigger lesson to learn here is not to assume that the mistake is in the library you're using. Always start with an expectation that the problem is in your own code. Sometimes you'll find it really is in the library or system code (or in the compiler etc) but in my experience that's relatively rare.
Related
I was trying represent some use-case scenario like below. I have json formatted data. And it include an enum class. They send this enum class with int type. I want to show this enum value with a meaningful string. But I couldn't make it.
How can I show this EnumMember custom value?
Edit: I want to show "Not Hot" value. Not Hot_Not enum.
static void Main(string[] args) {
var jsonString = "{\"Summary\":\"40\"}";
var options = new JsonSerializerOptions {
Converters = {
new JsonStringEnumConverter()
}
};
WeatherForecastWithEnum ? weatherForecast = JsonSerializer.Deserialize < WeatherForecastWithEnum > (jsonString, options) !;
Console.WriteLine(weatherForecast.Summary);
}
public class WeatherForecastWithEnum {
public Summary ? Summary {
get;
set;
}
}
public enum Summary {
Cold = 30,
Cool = 10,
Warm = 20,
[EnumMember(Value = "Not Hot")]
Hot_Not = 40
}
By default, it is not supported with System.Text.Json . You can see the request for the same.
https://github.com/dotnet/runtime/issues/31081
But there is an extension library called 'Macross.Json.Extensions' where you can use JsonStringEnumMemberConverter attribute and then do what you need.
JsonConverter(typeof(JsonStringEnumMemberConverter))]
public enum DefinitionType
{
[EnumMember(Value = "UNKNOWN_DEFINITION_000")]
DefinitionUnknown
}
[TestMethod]
public void ExampleTest()
{
string Json = JonSerializer.Serialize(DefinitionType.DefinitionUnknown);
Assert.AreEqual("\"UNKNOWN_DEFINITION_000\"", Json);
DefinitionType ParsedDefinitionType = JsonSerializer.Deserialize<DefinitionType>(Json);
Assert.AreEqual(DefinitionType.DefinitionUnknown, ParsedDefinitionType);
}
You can see more at - https://github.com/Macross-Software/core/tree/develop/ClassLibraries/Macross.Json.Extensions#enumerations
I've simplified my problem down to this bit of sample code using Newtonsoft.JSON.Linq and JObject.ToObject<T>()
The issue here is that in the constructor of Test a default value is added to the list Nums. However if I serialize and then deserialize the object, Newtonsoft is not replacing the list, but appending to the values set by the constructor.
I cannot change the deserialization process, as that is in a core library.
How can I set a default value for my list without duplication? Thanks.
class Test
{
public List<int> Nums { get; set; } = new List<int>();
public Test()
{
// add default value
this.Nums.Add(0);
}
}
class Program
{
static void Main(string[] args)
{
Test job = new Test(); // job.Nums.Count == 1
JObject jJob = JObject.FromObject(job);
job = jJob.ToObject<Test>(); // job.Nums.Count == 2
}
}
.Net Fiddle
Create ctor overload which takes default value.
class Test
{
public List<int> Nums { get; set; }
public Test()
{
this.Nums = new List<int>();
}
public Test(int def) : this()
{
this.Nums.Add(def);
}
}
Here is usage:
public class Program
{
public static void Main(string[] args)
{
Test job = new Test(0);
Console.WriteLine(job.Nums.Count);
JObject jJob = JObject.FromObject(job);
job = jJob.ToObject<Test>();
Console.WriteLine(job.Nums.Count); // This is 1 again.
}
}
You need to tell it how to deserialize the object
var serializer = new JsonSerializer {
ObjectCreationHandling = ObjectCreationHandling.Replace
};
job = jJob.ToObject<Test>(serializer);
Properly gives you 1 item after deserializing.
I have the following json object:
[
"sd",
[
"sdg\u0026e",
"sdlc",
"sdccu",
"sdsu webportal",
"sdsu",
"sdsu blackboard",
"sdcc",
"sd card",
"sdn",
"sdro"
]
]
Obtained from google suggest with this URL:
http://suggestqueries.google.com/complete/search?output=firefox&hl=en&q=sd
I have tried deserializing it like this:
dynamic objson = JsonConvert.DeserializeObject(res);
But it is not useful because I need it into a class object.
And also using types:
public class SuggestClass
{
public string search { get; set; }
public string[] terms { get; set; }
}
var result = JsonConvert.DeserializeObject<SuggestClass>(res);
But it always throw exception.
I do not know how can I do it without having name fields.
EDIT:
Another JSON:
["text",["textura","textos bonitos","texto argumentativo","textos","textos de amor","texto expositivo","texturas minecraft","textos de reflexion","texture pack minecraft","textos en ingles"]]
That's tricky...
But since it's an array, you could create a factory method to parse SuggestClass out of given JArray.
public void SomeMethod()
{
string json =
"[\"sd\",[\"sdg\u0026e\",\"sdlc\",\"sdccu\"" +
",\"sdsu webportal\",\"sdsu\",\"sdsu blackboard\","+
"\"sdcc\",\"sd card\",\"sdn\",\"sdro\"]]";
var factory = new Factory();
var suggest = factory.Create(json);
Console.WriteLine(suggest);
}
public class Factory
{
public SuggestClass Create(string json)
{
var array = JArray.Parse(json);
string search = array[0].ToString();
string[] terms = array[1].ToArray().Select(item => item.ToString()).ToArray();
return new SuggestClass {Search = search, Terms = terms};
}
}
public class SuggestClass
{
public string Search { get; set; }
public IEnumerable<string> Terms { get; set; }
public override string ToString()
{
return string.Format("Search={0},Terms=[{1}]",
Search, string.Join(",", Terms));
}
}
Would print to console:
Search=sd,Terms=[sdg&e,sdlc,sdccu,sdsu webportal,sdsu,sdsu blackboard,sdcc,sd card,sdn,sdro]
And the other JSON you provided:
Search=sd,Terms=[sdg&e,sdlc,sdccu,sdsu webportal,sdsu,sdsu blackboard,sdcc,sd card,sdn,sdro]
Search=text,Terms=[textura,textos bonitos,texto argumentativo,textos,textos de amor,texto expositivo,texturas minecraft,textos de reflexion,texture pack minecraft,textos en ingles]
Just used the JSON visualizer in visual studio. This is how it looks like.
It is an array of multiple types. The following code can be used to parse it. But it is not perfect yet.
var objson = JsonConvert.DeserializeObject<object[]>(res);
So I think #Mikko answer has a better approach..
I am having some trouble deserializing a Json string to use in an api wrapper I am currently writing. This is the json string in question:
{
"Search":[
{
"Title":"Clerks.",
"Year":"1994",
"imdbID":"tt0109445",
"Type":"movie"
},
{
"Title":"Clerks II",
"Year":"2006",
"imdbID":"tt0424345",
"Type":"movie"
}
]
}
This is the method I am currently using to process it.
public static Dictionary<string, string> FetchTitlesListDictionary(string searchQuery)
{
string searchResult = SendRequest(new[] { "?s=", searchQuery });
JObject parser = JObject.Parse(searchResult);
var movieDictionary = new Dictionary<string, string>();
for (int i = 0; i < parser["Search"].Count(); i++)
{
if (!movieDictionary.ContainsKey((string)parser["Search"][i]["imdbID"]))
{
movieDictionary.Add((string)parser["Search"][i]["imdbID"],
(string)parser["Search"][i]["Title"]);
}
}
return movieDictionary;
}
Even though the code above works, I feel it could, somehow, be made simpler.
How would I go about achieving this?
Thanks!
var obj = JsonConvert.DeserializeObject<RootObject>(searchResult);
public class Search
{
public string Title { get; set; }
public string Year { get; set; }
public string imdbID { get; set; }
public string Type { get; set; }
}
public class RootObject
{
public List<Search> Search { get; set; }
}
If you really want to convert the RootObject to a dictionary, you can use
var movieDictionary = obj.Search.ToDictionary(s => s.imdbID, s => s.Title);
PS: see this site
Well, if you're open to not using the default serializer, I would just open up the package manager console and type
Install-Package ServiceStack.Text
Then it becomes as easy as
var myDictionary = JsonObject.Parse(myJsonString)
.ArrayObjects("Search")
.ToDictionary(key => key.Get("imdbID"), value => value.Get("Title"));
There might be a similar and just as simple way to do it with the newtonsoft serializer, but honestly I never use it, so i'm not sure.
Also same thing as EZI's answer, it's also really easy if you have the objects he created, then you can just
var myObject = myJsonString.FromJson<RootObject>();
//if you want the dictionary it's the same thing, standard linq
var dictionary = myObject.Search.ToDictionary(x => x.imdbId, x => x.Title);
but if all you need is a dictionary, I would just use the above method, it's fast and easy.
I'm having some issues reading the properties of an item I have placed into an arraylist and I can't find the answer anywhere.
ArrayList itemsArrayList = new ArrayList();
itemsArrayList.Add(abyssalScepter);
itemsArrayList.Add(aegisOfTheLegion);
itemInBuildAbilityPower = itemsArrayList[0].abilityPower;
I need to be able to read the properties of the objects in the array so I can apply their values elsewhere but this gets me nowhere.
You need to cast object to the expected type (and hope it's really of this type).
itemInBuildAbilityPower = ((Item)itemsArrayList[0]).abilityPower;
The better option (if the infrastructure code is yours) to use generic container, e.g. List<T>.
List<Item> itemsArrayList = new List<Item>
itemsArrayList.Add(abyssalScepter);
itemsArrayList.Add(aegisOfTheLegion);
itemInBuildAbilityPower = itemsArrayList[0].abilityPower;
try
var itemInBuildAbilityPower = itemsArrayList[0].GetType().GetProperty ("abilityPower").GetGetMethod().Invoke (itemsArrayList[0], null);
Building on elder_george's answer, here is an example of what you could do if abyssalScepter and aegisOfTheLegion are not the exact same type:
using System.Collections.Generic;
class Power { }
interface IAbilityPower { Power abilityPower { get; set; } }
class Scepter : IAbilityPower { public Power abilityPower { get; set; } }
class Aegis : IAbilityPower { public Power abilityPower { get; set; } }
class Test
{
public static void Main()
{
var abyssalScepter = new Scepter();
var aegisOfTheLegion = new Aegis();
var itemsList = new List<IAbilityPower>();
itemsList.Add(abyssalScepter);
itemsList.Add(aegisOfTheLegion);
var power = itemsList[0].abilityPower;
}
}