C# JSON.net having trouble deserializing and reserializing object from file - c#

I am trying to get file with a list of users in JSON, de-serialize it into a list of user type objects, add a new user to that list and then re-serialize that list and write it to the file.
Here is the code I used.
public async void appendFile(User _user)
{
StorageFolder folder = ApplicationData.Current.LocalFolder;
StorageFile file = await folder.GetFileAsync("LocalUsers.txt");
string Json = await FileIO.ReadTextAsync(file);
List<User> users = JsonConvert.DeserializeObject<List<User>>(Json);
users.Add(_user);
string s = convertJson(users);
await FileIO.WriteTextAsync(file, s);
}
When the code is run it throws this error:
An exception of type 'Newtonsoft.Json.JsonSerializationException' occurred in Newtonsoft.Json.dll but was not handled in user code
Additional information: Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[Xymby.Models.User]' 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.
Not sure what I'm doing wrong here, any help would be appreciated also I would be open to any changes that are more efficient than my implementation.

Your json is a single entity of the User type, so it will not deserialize into a list. Wrap the json with [ ]'s and it will work. Make sure that when you write the json file in the future that you are only writing a collection type and not an individual user.
Given what you've supplied as the current json file, the following should do:
[{"ID":"d5d8fa11-1a95-4a73-9666-66671bc03d51","Name":"Brian"}]

Related

Get motion data for minut sensor using C#

I have an issue with getting only the motion sensor data using the minut Api, I try follow this documentation: https://api.minut.com/latest/docs#tag/Devices/paths/~1devices~1{device_id}~1motion_events/get
and I got an error:
Newtonsoft.Json.JsonSerializationException: 'Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'SensorReading+API_CustomEntity' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.
To fix this error either change the JSON to a JSON object (e.g. {"name":"value"}) or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List<T> that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.
Path '[0]', line 2, position 3.'
The error happens in this line of codes (the motion events), the rest of the codes there is no error:
List<SensorReading.API_CustomEntity> SoundLevelReadings = JsonConvert.DeserializeObject<List<SensorReading.API_CustomEntity>>(DeserializeAPIObj(SOUNDLEVEL));
List<SensorReading.API_CustomEntity> TemperatureReadings = JsonConvert.DeserializeObject<List<SensorReading.API_CustomEntity>>(DeserializeAPIObj(TEMPERATURE));
List<SensorReading.API_CustomEntity> HumidityReadings = JsonConvert.DeserializeObject<List<SensorReading.API_CustomEntity>>(DeserializeAPIObj(HUMIDITY));
List<SensorReading.API_CustomEntity> MotionEventsReadings = JsonConvert.DeserializeObject<List<SensorReading.API_CustomEntity>>(DeserializeAPIObj(MOTIONEVENTS));

C# Creating generic List from JArray

I'm working on a dynamic import proces from Json to object array.
Getting a little bit stuck by creating a List<> based on a string reference to the class object.
I'm importing json data from a REST server and using a business objects list to map the json data to predefined classes that can be configured. I'm using NewtonSoft.Json for the parsing of the data to classes.
string classname = "BusinessObjects.Contact";
Type classtype = Type.GetType(classname);
// ... filled jsonstring from api request
string json = "[]"; // json filled from rest request
JObject obj = JObject.Parse(json);
JArray array = (JArray)obj["contacts"];
// the issue part...
var records = array.ToObject<List<classtype>>();
The compiler states I'm using a variable as a type. Which makes sense, but can't find a way around it.
Any help would be appreciated!
Rather than deserializing your JArray, you could access it dynamically as shown in Querying JSON with dynamic. But if you would prefer to deserialize to a fixed list type, since you are writing non-generic reflection-based code, you can do:
var listType = typeof(List<>).MakeGenericType(classtype);
var records = array.ToObject(listType);
Notes:
Given an open generic type such as List<>, Type.MakeGenericType() creates a closed generic type by substituting the Type argument(s) for the type parameters of the open type.
JToken.ToObject() is a non-generic version of ToObject() that can deserialize to a specified Type.
Once you have created your records list you can cast it to the non-generic IList interface to access collections items.
Sample fiddle with prototype sample JSON and definition for BusinessObjects.Contact.

Error: Cannot deserialize the current JSON object

Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[Movie]' 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 'Movies', line 2, position 13.
You are trying to deserialize JSON into an array type but your JSON is not of type array.

NewtonSoft JsonConverter and the slash character

I am trying to create a dictionary from a Json array returned from a Web API which contains a file path value. I have extracted a sample here
JsonConvert.DeserializeObject<Dictionary<string, string>>("[{'Path':'\6\6553_20140729_134527059.mp3'}]")
Various combinations produce the following error. Only 1 approach works and I would love to know why. If someone can help.. much appreciated
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.
To fix this error either change the JSON to a JSON object (e.g. {"name":"value"}) or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List<T> that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.
Path '', line 1, position 1
The following throw the above error
//Escape with double slash
JsonConvert.DeserializeObject<Dictionary<string, string>>("[{'Path':'\\6\\6553_20140729_134527059.mp3'}]")
//Escape with quadruple slash
JsonConvert.DeserializeObject<Dictionary<string, string>>("[{'Path':'\\\\6\\\\6553_20140729_134527059.mp3'}]")
//Multiple Json Objects in array
JsonConvert.DeserializeObject<Dictionary<string, string>>("[{'Path':'\\6\\6553_20140729_134527059.mp3'},{'Path':'\\6\\6553_20140729_134527059.mp3'}]")
//Double slash, single Json object
JsonConvert.DeserializeObject<Dictionary<string, string>>("{'Path':'\\6\\6553_20140729_134527059.mp3'}")
This is the only thing that works
//Quadruple slash, single object
JsonConvert.DeserializeObject<Dictionary<string, string>>("{'Path':'\\\\6\\\\6553_20140729_134527059.mp3'}")
Like I said earlier, any help would be much appreciated
ALL THE TESTS DONE IN VISUAL STUDIO QUICK WATCH
When JSON starts with "[", it means that it represents List/Array, so the deserializer expect a List of some kind as parameter,
List<Dictionary<string, string>> in your case.

JSON.NET exception when deserializing an array of GUIDs

I'm using JSON.NET to deserialize AJAX HTTP requests sent in from the browser, and am running into problems with web service calls that use a Guid[] as a parameter. This worked fine when I used the built in .NET serializer.
First off, the raw bytes in the stream look like this:
System.Text.Encoding.UTF8.GetString(rawBody);
"{\"recipeIds\":[\"d9ede305-d244-483b-a435-abcf350efdb2\"]}"
I then call:
Newtonsoft.Json.JsonSerializer serializer = new Newtonsoft.Json.JsonSerializer();
parameters[0] = serializer.Deserialize(sr, operation.Messages[0].Body.Parts[0].Type);
.Type is System.Guid[]
I then get the exception:
Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Guid[]' 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<T>) 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 'recipeIds', line 1, position 13.
Web service methods that take in a single Guid (not an array) work, so I know JSON.NET is able to convert a string into a GUID, but it seems to blow up when you have an array of strings that you want to deserialize to an array of GUIDs.
Is this a JSON.NET bug, and is there a way to fix this? I suppose I could write my own custom Guid collection type, but I'd rather not.
You need a wrapper class
string json = "{\"recipeIds\":[\"d9ede305-d244-483b-a435-abcf350efdb2\"]}";
var obj = JsonConvert.DeserializeObject<Wrapper>(json);
public class Wrapper
{
public Guid[] recipeIds;
}
--EDIT--
Using Linq
var obj = (JObject)JsonConvert.DeserializeObject(json);
var guids = obj["recipeIds"].Children()
.Cast<JValue>()
.Select(x => Guid.Parse(x.ToString()))
.ToList();

Categories