Json array exception - c#

I create a Json file and insert some objects of my class inside it, like this:
private async void Save_Clicked(object sender, EventArgs e)
{
Note NoteNew = new Note
{
FraseGiorno = obj1.FraseGiornaliera,
Nota = TestoNota.Text,
Data= DateTime.Today.ToString().Remove(10,9),
};
File.WriteAllText(NotesFile, JsonConvert.SerializeObject(NoteNew));
}
Then when I try to read the file and deserialize the json I get this exception. how could i solve?
string NotesFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Note.json");
ObservableCollection<Note> listNote = new ObservableCollection<Note>();
FraseClass obj1;
public NotePage(FraseClass obj1)
{
InitializeComponent();
this.obj1 = obj1;
if (File.Exists(NotesFile))
{
listNote = JsonConvert.DeserializeObject<ObservableCollection<Note>>(File.ReadAllText(NotesFile));
CollectionNote.ItemsSource = listNote;
}
}
Newtonsoft.Json.JsonSerializationException: 'Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.ObjectModel.ObservableCollection`1[MotiVApp.NotePage+Note]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
Path 'FraseGiorno', line 1, position 15.'
I don't understand why the exception refers to the 'FraseGiorno' property

You are serializing an object into the file, but deserializing into a collection.
If you absolutely must use an ObservableCollection, separate the initialization and deserialization steps:
var note = JsonConvert.DeserializeObject<Note>(File.ReadAllText(NotesFile));
listNode.Add(note);
CollectionNote.ItemsSource = listNote;

Related

JsonConvert.DeserializeObject error while deserializing a string

I am trying to deserialize a json string that is coming from a js code, the data holds the json string that I want to deserialize.
The coming string is:
{"metalRingID":"FB11111","birdData":[{"longitude":-3.0851070084624497,"latitude":51.02832183751735,"gridRef":"ST2426","date":"2020-01-05T00:00:00"},{"longitude":-2.233409881591797,"latitude":51.5276985168457,"gridRef":null,"date":"2020-01-02T00:00:00"},{"longitude":-2.3790299892425537,"latitude":51.4547004699707,"gridRef":null,"date":"2020-01-03T00:00:00"},{"longitude":-1.6884700059890747,"latitude":51.68299865722656,"gridRef":null,"date":"2020-01-05T00:00:00"}]}
This is the model to hold that data:
using System;
using Newtonsoft.Json;
namespace BirdProject.Model.ViewModel
{
public class birdDataSolutionVM
{
[JsonProperty("metalRingID")]
public string metalRingID;
[JsonProperty("birdData")]
public List<birdRecordVM> birdData;
}
}
This is the line that should do the job.
var birdRecords = JsonConvert.DeserializeObject<List<birdDataSolutionVM>>(data);
The error I am receiving is the next:
Cannot deserialize the current JSON object (e.g. {"name":"value"})
into type
'System.Collections.Generic.List`1[BirdProject.Model.ViewModel.birdDataSolutionVM]'
because the type requires a JSON array (e.g. [1,2,3]) to deserialize
correctly.\nTo fix this error either change the JSON to a JSON array
(e.g. [1,2,3]) or change the deserialized type so that it is a normal
.NET type (e.g. not a primitive type like integer, not a collection
type like an array or List) that can be deserialized from a JSON
object. JsonObjectAttribute can also be added to the type to force it
to deserialize from a JSON object.\nPath 'metalRingID', line 1,
position 15.
You should be deserializing into the type, not an array of the type. It's a single object containing an array, but the root json is not an array.
var birdRecords = JsonConvert.DeserializeObject<birdDataSolutionVM>(data);

safe Serialize and Deserialize with Newtonsoft.Json

I have a code that takes messages of any type and serialize them into the DB, while saving the type of the message and the serialized json string.
I have a side process that should deserialize the messages later on and send them to the queue.
To perform the serialization and deserialization I use JsonConvert of Newtonsoft.Json:
For deserialization I use the following method:
object? DeserializeObject(string value, Type type)
For serialization I use the following method:
string SerializeObject(object? value)
I have the following questions:
A. I saw that in case DeserializeObject receives a wrong type name it still deserialize the object but his type is Newtonsoft.Json.Linq.JObject and not the type I passed into the method, I expected it will throw an exception, this behavior is very bad for us, is there any way to cause the deserialize to throw exception in this scenario?
B. Is the code below secured? I saw that the library has variabilities such as depicted here
private void StackOverflowQuestion()
{
Bus.Employees.Messages.LevelCreated levelCreated = new Bus.Employees.Messages.LevelCreated
{
Name = "director",
};
//var messageType = levelCreated.GetType().AssemblyQualifiedName;
string messageData = JsonConvert.SerializeObject(levelCreated);
//Deserialize with type that is not correct
object deserializeMessaged = DeserializeMessage("my cool type which does not exists!", messageData);
string theType = deserializeMessaged.GetType().FullName;//theType = Newtonsoft.Json.Linq.JObject
}
private object DeserializeMessage(string messageType, string messageSerializedData)
{
Type type = Type.GetType(messageType);
return JsonConvert.DeserializeObject(value: messageSerializedData, type);
}

How to pass "unknown" object as parameter and use it's original object type to deserialize

I am working on building a re-usable function to deserialize a JSON string.
The JSON deserialization routines need an object type(jsonTestObject). This all works as expected.
// serialize json to object
jsonTestObject testO = new jsonTestObject();
testO = Newtonsoft.Json.JsonConvert.DeserializeObject<jsonTestObject>(jsonString);
When I try to wrap this in a re-usable function to deserialize "any" object type I send, I run into issues. I am not sure how to pass the object type as a parameter to the function as I cant strongly type it.
I want to send "any" object type to my function and cast the result to my desired object type (As I will know what object type I am expecting when making the call.)
I don't want to hardcode a separate function for all classes that I want to serialize/deserialize.
Here is what I have that is not working...
JSONdeserialize(string jSONstring,Type t)
{
object newObject;
// deserialize object based on the original object type that was passed in.
newObject = JsonConvert.DeserializeObject<t>(jSONstring); //ERROR LINE
return newObject;
}
jsonTestObject jsonObject = new jsonTestObject();
object o = JSONdeserialize(jsonString, jsonObject.GetType());
jsonObject = (jsonTestObject)o;
ERROR: "'t' is a variable but is used like a type"
newObject = JsonConvert.DeserializeObject(jSONstring, t);
The code can be written in both the way.
public void JSONdeserialize<T>(string jSONstring)
{
return JsonConvert.DeserializeObject<T>(jSONstring);
}
jsonTestObject jsonObject = new jsonTestObject();
object o = JSONdeserialize<jsonTestObject>(jsonString);
jsonObject = (jsonTestObject)o;
or
public void JSONdeserialize(string jSONstring, Type type)
{
return JsonConvert.DeserializeObject(jSONstring, type);
}
jsonTestObject jsonObject = new jsonTestObject();
object o = JSONdeserialize(jsonString, typeof(jsonTestObject));
jsonObject = (jsonTestObject)o;

Can't deserialize JSON to Object [duplicate]

This question already has an answer here:
Cannot deserialize the current JSON array (e.g. [1,2,3])
(1 answer)
Closed 2 years ago.
I'm doing some testing in my program and I wanted to transform APIGatewayProxyResponse into a object to access it's values.
So an example of what my APIGatewayProxyResponse.Body (it's a string) looks like:
"[{"date": "2020-03-06", "value": 35},{"date": "2020-03-09", "value": 233}]"
I wanted to turn this into a dictionary at first, but I realized that perhaps it's not possible because a dictionary has unique key values and here I have a "date" and "value" properties that aren't unique.
var dic = JsonConvert.DeserializeObject<Dictionary<string, string>>(APIGatewayProxyResponse.Body);
Had a error, which proved my concern:
Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'System.Collections.Generic.Dictionary`2[System.String,System.String]' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.
So I made an ResponseObject to achieve the same result
public class ResponseObject
{
public string date { get; set; }
public double value { get; set; }
}
var dic = JsonConvert.DeserializeObject(APIGatewayProxyResponse.Body,typeof(ResponseObject));
But had the same error! I don't understand, the browser can look at the response and recognises it's a JSON format, so why ins't the same happening in in ASP.NET?
Because your Json is an array, So, you can Deserialize with IEnumerable type.
Try this:
var dic = JsonConvert.DeserializeObject<IEnumerable<ResponseObject>>(APIGatewayProxyResponse.Body);

Getting A List From Service Async

While trying to get list from an url, program stops and throw an exception like that
An exception of type 'System.AggregateException' occurred in mscorlib.dll but was not handled in user code
also
Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.IEnumerable`1[WebAPIDemo.Models.Person]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
Path 'Message', line 1, position 11.
I thought its because of using IEnumerable<MyObject> in my program but when I use only MyObject it goes away from this point but it crush into somewhere else.
I'm stuck now.
Here is my code:
CONTROLLER.CS:
private IEnumerable<Person> CallPersonListServiceAsync(HttpClient ins, string url)
{
var content = ins.GetAsync(url).Result.Content;
var personsList = content.ReadAsAsync(typeof(IEnumerable<Person>)).Result as IEnumerable<Person>;
return personsList;
}
PERSON.CS:
public class Person
{
public string name { get; set; }
public string surname { get; set; }
public DateTime dob { get; set; }
}
Is it really happening that because I'm using IEnumerable or something different. Thanks
The error is telling you that the JSON you're receiving is an object, not a collection. So you have to deserialize it to an object, not a collection. Unless the JSON is very different from what you expect (that is, not a Person at all) then you would simply deserialize it to a Person:
var result = content.ReadAsAsync(typeof(Person)).Result as Person;
Which would of course necessitate changing the return type (and name) of your method:
private Person CallPersonServiceAsync(HttpClient ins, string url)
Alternatively, instead of changing the method signature you could manufacture a list from that single person and return that:
return new List<Person> { result };
Additionally, the async nature of your code is very broken. For one thing, you are calling .Result explicitly which is almost always the wrong approach. Second, your method's name advertises it as an async method but it's not async at all.
You can correct both of these problems by making use of async and await:
private async Task<Person> CallPersonServiceAsync(HttpClient ins, string url)
{
var content = (await ins.GetAsync(url)).Content;
var result = (await content.ReadAsAsync(typeof(Person))) as IEnumerable<Person>;
return result;
}

Categories

Resources