Unexpected character encountered while parsing value: [ - c#

My JSON is as follows
{
"#odata.context":"https://graph.microsoft.com/V1.0/$metadata#users",
"value":[
{
"businessPhones":[
],
"displayName":"dee",
"givenName":null,
"jobTitle":null,
"mail":"79#gmail.com",
"mobilePhone":null,
"officeLocation":null,
"preferredLanguage":null,
"surname":null,
"userPrincipalName":"79_gmail.com#EXT##web.onmicrosoft.com",
"id":"08fab3-6f-4dc9-9ffb-6568d172"
},
{
"businessPhones":[
"973"
],
"displayName":"Technologies LLP",
"givenName":"SHA",
"jobTitle":null,
"mail":null,
"mobilePhone":"8762",
"officeLocation":null,
"preferredLanguage":"en-U",
"surname":"SHAI",
"userPrincipalName":"admin#web.onmicrosoft.com",
"id":"2adf-94cd-45-83ef-d0dbf1e36"
},
{
"businessPhones":[
],
"displayName":"admin of smartogle",
"givenName":null,
"jobTitle":null,
"mail":null,
"mobilePhone":null,
"officeLocation":null,
"preferredLanguage":"en-US",
"surname":null,
"userPrincipalName":"admin#smartogle.com",
"id":"1754-d6-40-9ae2-d816063e"
},
{
"businessPhones":[
],
"displayName":"av",
"givenName":null,
"jobTitle":null,
"mail":null,
"mobilePhone":null,
"officeLocation":null,
"preferredLanguage":"en-US",
"surname":null,
"userPrincipalName":"av#smartogle.com",
"id":"6837-08-449-a6ab-78b"
}
]
}
I am using the following code to convert the json to the object list
MyObject obj = JsonConvert.DeserializeObject<MyObject>(members);
MyObject Class is as follows
public class MyError
{
public List<values> value;
}
public class values
{
public string id;
public string userPrincipalName;
public string surname;
public string preferredLanguage;
public string officeLocation;
public string mobilePhone;
public string mail;
public string jobTitle;
public string givenName;
public string displayName;
public string businessPhones;
}
While converting I am getting the following error
Unexpected character encountered while parsing value: [. Path 'value[0].businessPhones', line 1, position 97.
When I delete the public string businessPhones; from the class the rest of the data are parsed to the object list. But actually I need the businessPhones also

as several folks pointed about you should declare businessPhones as array:
public string[] businessPhones;

Related

How do I get info from an object with an array of objects in a json for Unity?

I have a JSON file setup as such
{
"cards": [
{
"id": "sand_bags",
"type": "Structure",
"name": "Sand Bags",
"values": [
{
"civilian": 1,
"fiend": -1
}
],
"effectTexts": [
{
"civilian": "Add +1 to your BUNKER.",
"fiend": "Send any CIVILIAN'S +1 STRUCTURE to the SCRAPYARD."
}
],
"flavorTexts": [
{
"civilian": "They're just heavy bags with sand. Not much else to say, but they'll slow down an attack from a fiend. Good luck, you'll need it!",
"fiend": "You've spotted a pretty bad STRUCTURE in this BUNKER. Time to do some damage."
}
],
"staysOnField": [
{
"civilian": true,
"fiend": false
}
],
"amountInDeck": 5
}
]
}
I also have a Cards script
[Serializable]
public class Cards
{
public Card[] cards;
}
[Serializable]
public class Card
{
public string id;
public string type;
public string name;
public int amountInDeck;
}
public class Values
{
public int civilian;
public int fiend;
}
I then have a CardEffects script that I'm using for my functions.
public class CardEffects : MonoBehaviour
{
public TextAsset jsonFile;
public Values values;
void Start()
{
Cards cardsInJson = JsonUtility.FromJson<Cards>(jsonFile.text);
foreach (Card card in cardsInJson.cards)
{
Debug.Log("Card name: " + card.name + " with " + values.civilian + " in the deck.");
}
}
}
I have searched all over trying to figure out how to even get the array of objects of "values". I got this far and the value printed is always 0 regardless of the information in "values" in the JSON. If I make the class Serializable, I'm able to change the values and it works but I want the values to be whatever they were declared as in the JSON. Is there a better way to do this?
Please keep in mind I'm new to C# and Unity. I usually code in JS in which using JSON files are no big deal for me and thought it was the best way to go.
Your json and your classes doesn't match. Not only that your json isn't even valid Json. Below I will give you your correct json and class.
{
"cards": [
{
"id": "sand_bags",
"type": "Structure",
"name": "Sand Bags",
"values": [
{
"civilian": 1,
"fiend": -1
}
],
"effectTexts": [
{
"civilian": "Add +1 to your BUNKER.",
"fiend": "Send any CIVILIAN'S +1 STRUCTURE to the SCRAPYARD."
}
],
"flavorTexts": [
{
"civilian": "They're just heavy bags with sand. Not much else to say, but they'll slow down an attack from a fiend. Good luck, you'll need it!",
"fiend": "You've spotted a pretty bad STRUCTURE in this BUNKER. Time to do some damage."
}
],
"staysOnField": [
{
"civilian": true,
"fiend": false
}
],
"amountInDeck": 5
}
] // <---- This was missing
}
For that Json this is how your card class will have to look like:
public Card
{
public string id { get; set; }
public string type { get; set; }
public string name { get; set; }
public Values[] values { get; set; }
public Values[] effectTexts { get; set; }
public Values[] staysOnField { get; set; }
public int amountInDeck { get; set; }
}
And your Values class have to look like this:
public class Values
{
public object civilian;
public object fiend;
}
I suggest MiniJson.
You can just copy paste the script to your project and you are ready to go.
The then can call Json.Deserialize(string json) passing your string in. For the case of an array you can do for example:
IList myJsonElements = (IList)Json.Deserialize(string json);
Find working snippet:
using System;
using Newtonsoft.Json;
namespace ConsoleApp3
{
class Program
{
static void Main(string[] args) {
string myJson = "{\"cards\": [{\"id\": \"sand_bags\",\"type\": \"Structure\",\"name\": \"Sand Bags\",\"values\": [{\"civilian\": 1,\"fiend\": -1}],\"effectTexts\": [{\"civilian\": \"Add +1 to your BUNKER.\",\"fiend\": \"Send any CIVILIAN'S +1 STRUCTURE to the SCRAPYARD.\"}],\"flavorTexts\": [{\"civilian\": \"They're just heavy bags with sand. Not much else to say, but they'll slow down an attack from a fiend. Good luck, you'll need it!\",\"fiend\":\"You've spotted a pretty bad STRUCTURE in this BUNKER. Time to do some damage.\"}],\"staysOnField\": [{\"civilian\": true,\"fiend\": false}],\"amountInDeck\": 5}]}";
var myJsonElements = MiniJSON.Json.Deserialize(myJson);
Console.WriteLine(myJsonElements.ToString());
string json = JsonConvert.SerializeObject(myJsonElements, Formatting.Indented);
Console.WriteLine(json);
Console.ReadLine();
}
}
}

Deserialize nested objects with JsonUtility

I would like to deserialize my json files holding information about levels. Given this example .json file called 1.json
{
"name": "Level One",
"map": [
[{
"groundTexture": "grass",
"cellType": "empty",
"masterField": null,
"worldObjects": [{
"worldObjectType": "player",
"rotation": 90
}]
},{
"groundTexture": "grass",
"cellType": "obstacle",
"masterField": null,
"worldObjects": [{
"worldObjectType": "tree",
"rotation": 0
}]
}],[{
"groundTexture": "grass",
"cellType": "campFire",
"masterField": null,
"worldObjects": [{
"worldObjectType": "campfire",
"rotation": 270
}]
},{
"groundTexture": "grass",
"cellType": "related",
"masterField": {
"x": 1,
"y": 0
},
"worldObjects": []
}]
]
}
I would like to convert the data from that file to a class object holding all the data needed to create a level during runtime. I created a reader which only reads the file content
public class LevelReader : MonoBehaviour
{
private string levelBasePath;
private void Awake()
{
levelBasePath = $"{Application.dataPath}/ExternalFiles/Levels";
}
public string GetFileContent(string levelName)
{
string file = $"{levelName}.json";
string filePath = Path.Combine(levelBasePath, file);
return File.ReadAllText(filePath);
}
}
and a mapper which maps the json string to a LevelInfo object.
public class LevelMapper : MonoBehaviour
{
private void Start()
{
// DEBUGGING TEST
LevelReader levelReader = GetComponent<LevelReader>();
string levelContent = levelReader.GetFileContent("1");
LevelInfo levelInfo = MapFileContentToLevelInfo(levelContent);
Debug.Log(levelInfo.cells);
}
public LevelInfo MapFileContentToLevelInfo(string fileContent)
{
return JsonUtility.FromJson<LevelInfo>(fileContent);
}
}
The following structs just help to create an object containg all the level data:
[Serializable]
public struct LevelInfo
{
public string name;
public LevelCell[][] cells;
}
[Serializable]
public struct LevelCell
{
public string groundTexture;
public string cellType;
public Vector2? masterField;
public LevelWorldObject[] worldObjects;
}
[Serializable]
public struct LevelWorldObject
{
public string worldObjectType;
public int rotation;
}
When starting the application the mapper runs and loops through the data object. Unfortunately the cells are null. How can I deserialize the file correctly?
In LevelInfo structure you have field "cells" but in Json - "map". They must be the same.
JsonUtility can't serialize/deserialize multidimensional arrays.
https://answers.unity.com/questions/1322769/parsing-nested-arrays-with-jsonutility.html
https://docs.unity3d.com/Manual/script-Serialization.html
I believe you can change your data structures or use another serializer.

JsonUtility in Unity is not working anymore. Why?

I'm trying to get a integer value from a Json that I GET from a server. I used JsonUtility from Unity libreries and It was working fine. And suddenly it is not parsing anymore.
All values returned are Null.
//SAMPLE CODE
SpinResult res = JsonUtility.FromJson<SpinResult>(download.downloadHandler.text);
spinValue = res.result;
//spinValue is always 0. It was working fine
//CLASS
[System.Serializable]
public class SpinResult
{
public int result;
}
//JSON
{
"data": {
"type": "",
"id": "",
"attributes": {
"server_seed": "",
"client_seed": "",
"result": 31,
},
"next_spin": {
"hashed_server_seed": "",
"client_seed": ""
}
}
}
I just need the integer "RESULT", in this case it should be 31 but the actual output is always 0. I check the Json everytime and its working perfectly fine.
I have not tested this, but try making your class look like this:
[System.Serializable]
public class SpinResult
{
public string type;
public string id;
public Attributes attributes;
}
[System.Serializable]
public class Attributes
{
public string server_seed;
public string client_seed;
public int result;
}
Then to get the value of result you would use:
int spinValue = res.attributes.result;

Deserialize JSON value without name

How can I deserialize a string in C# that only have values and no name. It looks like this: The problem is that this stream of string does not have name and uses array.
{
"result": {
"14400": [
[
1502985600,
262.18,
262.18,
257,
257,
1096.0131
],
[
1503000000,
257,
261.33,
254.8,
257,
1130.5897
]
],
"14405": [
[
1503014400,
258.03,
261.5,
257.01,
257.01,
520.7805
],
[
1503028800,
258,
260.98,
252.4,
259.56,
298.5658
],
]
]
}
}
Just create a class like
public class Root
{
public Dictionary<int,List<List<double>>> Result { get; set; }
}
and deserialize as
var res = JsonConvert.DeserializeObject<Root>(json);
I see it's an array, you could create a method to parse the class out of given JArray.
The Jason data
public void methpod()
{
string json ="Your jason value "
var factory = new Factory();
var suggest = factory.Create(json);
Console.WriteLine(suggest);
}
Make a class as suggested :
public class Factory
{
public Evan 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 Evan{Search = search, Terms = terms};
}
}
and another
public class Evan
{
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));
}
}
Tip
If you have JSON that you want to deserialize, and you don't have the class to deserialize it into, Visual Studio 2019 can automatically generate the class you need:
Copy the JSON that you need to deserialize.
Create a class file and delete the template code.
Choose Edit > Paste Special > Paste JSON as Classes.
The result is a class that you can use for your deserialization target

AOP Logging with custom arguments

Before every method executes, I want to log all parameters from that method. For that, I would use AOP (Aspect oriented programming) and create a "Loggable" attribute. But... I also would like to know the content of my parameters. For a string-parameter, that's not a problem. But I would like to know a good solution for every occasion, like objects, ints, doubles,...
Is there any other way to solve this other then to overwrite the ToString() method?
(in examples I always came across a string parameter...)
Example:
public class MyType {
public int Id { get; set; }
public string Name { get; set; }
public double Value { get; set; }
}
[Loggable]
public void IDoWhateverIWant(MyType data, int count, string message){
//Whatever I want
}
IDoWhateverIWant(
new MyType(){
Id = 1,
Name = "My test data name",
Value = 1234.56}
, 5
, "Log me, please");
Logmessage (the way these parameters are presented are the same to me, I just want to see them):
22/07/2014 9:30 Incoming message: IDoWhateverIWant with parameters:
- data : Id = 1
Name = "My test data name"
Value = 1234.56
- count: 5
- message: "Log me, please"
A simple option is to use NewtonSoft.Json to serialize each parameter. This simple example:
public void IDoWhateverIWant(MyType data, int count, string message)
{
string logMessage =
ParameterValueMessage(data, "data") + Environment.NewLine +
ParameterValueMessage(count, "count") + Environment.NewLine +
ParameterValueMessage(message, "message");
Debug.Print(logMessage);
}
public static string ParameterValueMessage<T>(T arg, string name)
{
string result = JsonConvert.SerializeObject(arg, Formatting.Indented);
return name + ": " + result;
}
Produces the following:
data: {
"Id": 1,
"Name": "My test data name",
"Value": 1234.56
}
count: 5
message: "Log me, please"
My own preference though is for each method to take a single parameter object - the logging code is a lot neater and more generic with parameter objects and all of the individual parameter names can be inferred from the parameter object:
public class MyParameterObject
{
public MyType data { get; set; }
public int count { get; set; }
public string message { get; set; }
}
which is serialized in much the same way and has the benefit of not having to pass in the name of every individual parameter:
public void IAlsoDoWhateverIWant(MyParameterObject parameterObject)
{
string logMessage = ParameterValueMessage(parameterObject);
Debug.Print(logMessage);
}
public static string ParameterValueMessage<T>(T arg)
{
return JsonConvert.SerializeObject(arg, Formatting.Indented);
}
and produces the following output:
{
"data": {
"Id": 1,
"Name": "My test data name",
"Value": 1234.56
},
"count": 5,
"message": "Log me, please"
}

Categories

Resources