Facebook deserializing - json

I need help deserializing the JSON i get back from facebook.
I've been trying numerous ways to parse it but no success.
The only thing i seem to be parsing is the number of friends who have highscores, which is 2 :
The issue comes when I try to parse the name and score of the people in the json.
InvalidCastException: Cannot cast from source type to destination type.
I/Unity (21869): at FacebookScript.GETCallback (IGraphResult result) [0x00000] in <filename unknown>:0
I/Unity (21869): at Facebook.Unity.AsyncRequestString+<Start>c__Iterator1.MoveNext () [0x00000] in <filename unknown>:0
The raw result which I recieve (seen from logcat):
Raw:{"data":[{"score":60,"user":{"name":"JOHNY JOHN","id":"0000000000000"}},{"score":50,"user":{"name":"JOHN JOHN","id":"0000000000000"}}]}
Here is my code:
public void GETCallback(IGraphResult result)
{
if (result.ResultDictionary != null)
{
Debug.Log("Raw:" + result.RawResult);
var dict = Json.Deserialize(result.RawResult) as Dictionary<string, object>;
var friendList = new List<object>();
friendList = (List<object>)(dict["data"]);
int _friendCount = friendList.Count;
Debug.Log("Items found:" + _friendCount);
List<string> friendIDsFromFB = new List<string>();
/*for (int i = 0; i < _friendCount; i++) // Tried this, same error.
{
foreach(KeyValuePair<string, object> entry in friendList)
{
Debug.Log(entry.Key + "|" + entry.Value);
}
string friendFBID = getDataValueForKey((Dictionary<string, object>)(friendList[i]), "id");
string friendName = getDataValueForKey((Dictionary<string, object>)(friendList[i]), "name");
Debug.Log(i + "/" + _friendCount + "|" + friendFBID +"|"+ friendName);
NPBinding.UI.ShowToast(i + "/" + _friendCount + "|" + friendFBID + "|" + friendName, VoxelBusters.NativePlugins.eToastMessageLength.LONG);
//friendIDsFromFB.Add(friendFBID);
}*/
foreach(KeyValuePair<string, object> entry in friendList) // Tried this, same error.
{
Debug.Log(entry.Key + "|" + entry.Value);
}
}
else
{
NPBinding.UI.ShowToast("result.ResultDictionary is null", VoxelBusters.NativePlugins.eToastMessageLength.LONG);
}
}
private string getDataValueForKey(Dictionary<string, object> dict, string key)
{
object objectForKey;
if (dict.TryGetValue(key, out objectForKey))
{
return (string)objectForKey;
}
else {
return "";
}
}

I'm assuming that you're using MiniJSON (at least the version that used to come with the FB SDK)
N.B. Not tested for typos. Typing straight here in SO
var dict = Json.Deserialize(result.RawResult) as Dictionary<string, object>;
var datas = (List<object>)dict["data"];
foreach(var iterator in datas) {
var data = iterator as Dictionary<string, object>;
Debug.Log("Score is :: "+data["score"]);
//var score = int.Parse((string)data["score"]); //Parse to int after casting to string if you want the value
var userData = data["user"] as Dictionary<string, object>;
Debug.Log("Name is :: "+userData["name"]);
Debug.Log("ID is :: "+userData["id"]);
//var name = (string)userData["name"]; //Get the name
//var id = (string)userData["id"]; //...and the ID
}

Related

Serializing and deserializing objects

I am trying to serialize and deserialize my objects to save and load data.
I thought I was smart and introduced Attributes:
[ExposedProperty]
public float Width { get; set; }
[ExposedProperty]
public Color HoverColor { get; set; }
I have a PropertyData class:
[System.Serializable]
public class PropertyData
{
public string Name;
public string Type;
public object Value;
public override string ToString()
{
return "PropertyData ( Name = " + Name + ", Type = " + Type + ", Value = " + Value + ")";
}
}
So instead of writing an ObjectData class for every Object class I have that gets serialized into JSON, I though I'd write a Serializable class that does:
public List<PropertyData> SerializeProperties()
{
var list = new List<PropertyData>();
var type = this.GetType();
var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty)
.Where(p => p.GetCustomAttributes(typeof(ExposedPropertyAttribute), false).Length > 0)
.ToArray();//
for (int i = 0; i < properties.Length; i++)
{
var property = properties[i];
var data = new PropertyData();
data.Name = property.Name;
data.Type = property.PropertyType.Name;
data.Value = property.GetValue(this);
list.Add(data);
}
return list;
}
and also to deserialize:
protected void DeserializePropertyData(PropertyData data)
{
var p = this.GetType().GetProperty(data.Name);
if (p == null)
{
Debug.LogError("Item " + this + " does not have a property with name '" + data.Name + "'");
return;
}
var type = p.PropertyType;
try
{
//TODO do some magic here to deserialize any of the values.
TypeConverter typeConverter = TypeDescriptor.GetConverter(type);
object propValue = typeConverter.ConvertFromString(data.Value);
p.SetValue(this, propValue);
}
catch(FormatException fe)
{
Debug.Log($"Serializable, there was a format exception on property {data.Name} and value {data.Value} for type {type}");
}
catch(NotSupportedException nse)
{
Debug.Log($"Serializable, there was a not supported exception on property {data.Name} and value {data.Value} for type {type}");
}
finally
{
}
}
But as it turns out, I can't serialize or deserialize Color, or Vector3, or Quaternion, or whatever. It only works for bool, float, string, int...
Any ideas how to serialize/deserialize other objects properly?
Thanks for all the answers. I looked into the ISerializationSurrogate Interface and noticed that it can't be used for UnityEngine.Vector3 or UnityEngine.Color classes.
Then I looked into TypeConverter and also saw that you can't directly use it because you have to add the attribute [TypeConverter(typeof(CustomTypeConverter))] on top of the very class or struct you want to convert.
And at the end of the day, both TypeConverter and ISerializationSurrogate are simply pushing and parsing chars around to get the result. For a Vector3, you have to trim the "(", ")", split the string with a "," and perform float.Parse on every element of the split string array. For a Color, you have to trim "RGBA(" and ")", and do the exact same thing.
Deadline is tight, so I took the same principle and created a static class that does my converting:
public static class MyCustomTypeConverter
{
public static object ConvertFromString(string value, Type destinationType)
{
if (destinationType == typeof(string))
{
return value;
}
else if (destinationType == typeof(int))
{
return int.Parse(value);
}
else if (destinationType == typeof(float))
{
return float.Parse(value);
}
else if (destinationType == typeof(double))
{
return double.Parse(value);
}
else if (destinationType == typeof(long))
{
return long.Parse(value);
}
else if (destinationType == typeof(bool))
{
return bool.Parse(value);
}
else if (destinationType == typeof(Vector3))
{
var mid = value.Substring(1, value.Length - 2);
var values = mid.Split(",");
return new Vector3(
float.Parse(values[0], CultureInfo.InvariantCulture),
float.Parse(values[1], CultureInfo.InvariantCulture),
float.Parse(values[2], CultureInfo.InvariantCulture)
);
}
else if (destinationType == typeof(Vector4))
{
var mid = value.Substring(1, value.Length - 2);
var values = mid.Split(",");
return new Vector4(
float.Parse(values[0], CultureInfo.InvariantCulture),
float.Parse(values[1], CultureInfo.InvariantCulture),
float.Parse(values[2], CultureInfo.InvariantCulture),
float.Parse(values[3], CultureInfo.InvariantCulture)
);
}
else if (destinationType == typeof(Color))
{
var mid = value.Substring(5, value.Length - 6);
var values = mid.Split(",");
return new Color(
float.Parse(values[0], CultureInfo.InvariantCulture),
float.Parse(values[1], CultureInfo.InvariantCulture),
float.Parse(values[2], CultureInfo.InvariantCulture),
float.Parse(values[3], CultureInfo.InvariantCulture)
);
}
else if (destinationType == typeof(PrimitiveType))
{
var e = Enum.Parse<PrimitiveType>(value);
return e;
}
else if (destinationType == typeof(SupportedLightType))
{
var e = Enum.Parse<SupportedLightType>(value);
return e;
}
return null;
}
public static string ConvertToString(object value)
{
return value.ToString();
}
}
It works, does what I want, and I can extend it for further classes or structs. Quaternion or Bounds perhaps, but I don't need much more than that.
My Serialization class now does this:
public List<PropertyData> SerializeProperties()
{
var list = new List<PropertyData>();
var type = this.GetType();
var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty)
.Where(p => p.GetCustomAttributes(typeof(ExposedPropertyAttribute), false).Length > 0)
.ToArray();//
for (int i = 0; i < properties.Length; i++)
{
var property = properties[i];
var data = new PropertyData();
data.Name = property.Name;
data.Value = MyCustomTypeConverter.ConvertToString(property.GetValue(this));
list.Add(data);
}
return list;
}
and that:
protected void DeserializePropertyData(PropertyData data)
{
var p = this.GetType().GetProperty(data.Name);
if (p == null)
{
return;
}
var type = p.PropertyType;
object propValue = MyCustomTypeConverter.ConvertFromString(data.Value, type);
p.SetValue(this, propValue);
}

Read arbitrarily json data to a javafx treeview,and only show the first element of any array in it

I need to show a json file on a javafx treeview,the structure of the json is unknown.Like the web site: json viewer site
I show the tree for user to select path of a value(like xpath of xml),so if the json is too big,I only need to show the first element of any array in json.
for example,the original data is:
{
name:"tom",
schools:[
{
name:"school1",
tags:["maths","english"]
},
{
name:"school2",
tags:["english","biological"]
},
]
}
I want to show:
again:the structure of json is unknown,it is just one example.
There's no other option than recursively handling the json and create the TreeItem structure based on the element info.
(There's probably a better way of adding the symbols, but I didn't find appropriate icons.)
private static final String INPUT = "{\n"
+ " name:\"tom\",\n"
+ " schools:[\n"
+ " {\n"
+ " name:\"school1\",\n"
+ " tags:[\"maths\",\"english\"]\n"
+ " },\n"
+ " {\n"
+ " name:\"school2\",\n"
+ " tags:[\"english\",\"biological\"]\n"
+ " },\n"
+ " ]\n"
+ "}";
private static final Image JSON_IMAGE = new Image("https://i.stack.imgur.com/1slrh.png");
private static void prependString(TreeItem<Value> item, String string) {
String val = item.getValue().text;
item.getValue().text = (val == null
? string
: string + " : " + val);
}
private enum Type {
OBJECT(new Rectangle2D(45, 52, 16, 18)),
ARRAY(new Rectangle2D(61, 88, 16, 18)),
PROPERTY(new Rectangle2D(31, 13, 16, 18));
private final Rectangle2D viewport;
private Type(Rectangle2D viewport) {
this.viewport = viewport;
}
}
private static final class Value {
private String text;
private final Type type;
public Value(Type type) {
this.type = type;
}
public Value(String text, Type type) {
this.text = text;
this.type = type;
}
}
private static TreeItem<Value> createTree(JsonElement element) {
if (element.isJsonNull()) {
return new TreeItem<>(new Value("null", Type.PROPERTY));
} else if (element.isJsonPrimitive()) {
JsonPrimitive primitive = element.getAsJsonPrimitive();
return new TreeItem<>(new Value(primitive.isString()
? '"' + primitive.getAsString() + '"'
: primitive.getAsString(), Type.PROPERTY));
} else if (element.isJsonArray()) {
JsonArray array = element.getAsJsonArray();
TreeItem<Value> item = new TreeItem<>(new Value(Type.ARRAY));
// for (int i = 0, max = Math.min(1, array.size()); i < max; i++) {
for (int i = 0, max = array.size(); i < max; i++) {
TreeItem<Value> child = createTree(array.get(i));
prependString(child, Integer.toString(i));
item.getChildren().add(child);
}
return item;
} else {
JsonObject object = element.getAsJsonObject();
TreeItem<Value> item = new TreeItem<>(new Value(Type.OBJECT));
for (Map.Entry<String, JsonElement> property : object.entrySet()) {
TreeItem<Value> child = createTree(property.getValue());
prependString(child, property.getKey());
item.getChildren().add(child);
}
return item;
}
}
#Override
public void start(Stage primaryStage) {
JsonParser parser = new JsonParser();
JsonElement root = parser.parse(INPUT);
TreeItem<Value> treeRoot = createTree(root);
TreeView<Value> treeView = new TreeView<>(treeRoot);
treeView.setCellFactory(tv -> new TreeCell<Value>() {
private final ImageView imageView;
{
imageView = new ImageView(JSON_IMAGE);
imageView.setFitHeight(18);
imageView.setFitWidth(16);
imageView.setPreserveRatio(true);
setGraphic(imageView);
}
#Override
protected void updateItem(Value item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null) {
setText("");
imageView.setVisible(false);
} else {
setText(item.text);
imageView.setVisible(true);
imageView.setViewport(item.type.viewport);
}
}
});
final Scene scene = new Scene(treeView);
primaryStage.setScene(scene);
primaryStage.show();
}

JSON Array conversion to CSV

I want to convert JSON to CSV. I am using the list function to meet the purpose.
But I am not getting desirable output for JSON array. Please find the sample JSON and list function which I am using:
Sample JSON document:
{
"NAME": "Viv",
"EMAIL": "lo",
"PUBLIC_OFFICIALS_CONTACTED": [{
"NAME_PUBLIC_OFFICIAL": [ "ff"],
"TITLE_PUBLIC_OFFICIAL": ["ff"]
}]
,
"COMMUNICATION_TYPE": ["Meeting","Phone","Handout","Conference"],
"NAMES_OF_OTHERS_FROM_XXX": [{
"NAME_OF_OTHERS": ["ff"],
"TITLE_OF_OTHERS": [ "ff"]
}]
,
"COMMUNICATION_BENEFIT": "Yes",
"AFFILIATE_NAME": "name",
"COMMUNICATION_ARRANGED": "Yes, arranged by you"
}
and list function which I am using is:
function(head, req) {
var row,
first = true;
// output HTTP headers
start({
headers: {
'Content-Type': 'text/csv'
}
,
});
// iterate through the result set
while(row = getRow()) {
// get the doc (include_docs=true)
var doc = row.doc;
// if this is the first row
if (first) {
// output column headers
send(Object.keys(doc).join(',') + 'n');
first = false;
}
// build up a line of output
var line = '';
// iterate through each row
for(var i in doc) {
// comma separator
if (line.length > 0) {
line += ',';
}
// output the value, ensuring values that themselves
// contain commas are enclosed in double quotes
var val = doc[i];
if (typeof val == 'string' && val.indexOf(',') > -1) {
line += '"' + val.replace(/"/g,'""') + '"';
}
else {
line += val;
}
}
line += 'n';
// send the line
send(line);
}
};
Please find attached the CSV output and expected output exported in excel.
Also, there is an issue in saving checkbox values. Please help me in writing the list function for the above JSON conversion to CSV.
current output:
expected output:
CSV is a single, flat list of values in each row, and one row of headers. The expected output shared in this question isn't compatible with CSV - it will be necessary to "flatten" your JSON by unpacking the nested data structures and making them instead into a flat hierarchy of data that can then become CSV. Try searching for "JSON to CSV" with a search engine for some examples - hope that helps!
I have refered this gitHUb link and tried the following:
JsonFlattener.class : Which will read the json string & extract the key & value
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.*;
public class JsonFlattener {
public Map<String, String> parse(JSONObject jsonObject) throws JSONException {
Map<String, String> flatJson = new HashMap<String, String>();
flatten(jsonObject, flatJson, "");
return flatJson;
}
public List<Map<String, String>> parse(JSONArray jsonArray) throws JSONException {
List<Map<String, String>> flatJson = new ArrayList<Map<String, String>>();
int length = jsonArray.length();
for (int i = 0; i < length; i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
Map<String, String> stringMap = parse(jsonObject);
flatJson.add(stringMap);
}
return flatJson;
}
public List<Map<String, String>> parseJson(String json) throws Exception {
List<Map<String, String>> flatJson = null;
try {
JSONObject jsonObject = new JSONObject(json);
flatJson = new ArrayList<Map<String, String>>();
flatJson.add(parse(jsonObject));
} catch (JSONException je) {
flatJson = handleAsArray(json);
}
return flatJson;
}
private List<Map<String, String>> handleAsArray(String json) throws Exception {
List<Map<String, String>> flatJson = null;
try {
JSONArray jsonArray = new JSONArray(json);
flatJson = parse(jsonArray);
} catch (Exception e) {
throw new Exception("Json might be malformed");
}
return flatJson;
}
private void flatten(JSONArray obj, Map<String, String> flatJson, String prefix) throws JSONException {
int length = obj.length();
for (int i = 0; i < length; i++) {
if (obj.get(i).getClass() == JSONArray.class) {
JSONArray jsonArray = (JSONArray) obj.get(i);
if (jsonArray.length() < 1) continue;
flatten(jsonArray, flatJson, prefix + i);
} else if (obj.get(i).getClass() == JSONObject.class) {
JSONObject jsonObject = (JSONObject) obj.get(i);
flatten(jsonObject, flatJson, prefix + (i + 1));
} else {
String value = obj.getString(i);
if (value != null)
flatJson.put(prefix + (i + 1), value);
}
}
}
private void flatten(JSONObject obj, Map<String, String> flatJson, String prefix) throws JSONException {
Iterator iterator = obj.keys();
while (iterator.hasNext()) {
String key = iterator.next().toString();
if (obj.get(key).getClass() == JSONObject.class) {
JSONObject jsonObject = (JSONObject) obj.get(key);
flatten(jsonObject, flatJson, prefix);
} else if (obj.get(key).getClass() == JSONArray.class) {
JSONArray jsonArray = (JSONArray) obj.get(key);
if (jsonArray.length() < 1) continue;
flatten(jsonArray, flatJson, key);
} else {
String value = obj.getString(key);
if (value != null && !value.equals("null"))
flatJson.put(prefix + key, value);
}
}
}
}
CSVWriter.class:Which transform the json string to CSV file
import org.apache.commons.lang.StringUtils;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.util.*;
public class CSVWriter {
public void writeAsCSV(List<Map<String, String>> flatJson, String fileName) throws FileNotFoundException {
Set<String> headers = collectHeaders(flatJson);
String output = StringUtils.join(headers.toArray(), ",") + "\n";
for (Map<String, String> map : flatJson) {
output = output + getCommaSeperatedRow(headers, map) + "\n";
}
writeToFile(output, fileName);
}
private void writeToFile(String output, String fileName) throws FileNotFoundException {
BufferedWriter writer = null;
try {
writer = new BufferedWriter(new FileWriter(fileName));
writer.write(output);
} catch (IOException e) {
e.printStackTrace();
} finally {
close(writer);
}
}
private void close(BufferedWriter writer) {
try {
if (writer != null) {
writer.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
private String getCommaSeperatedRow(Set<String> headers, Map<String, String> map) {
List<String> items = new ArrayList<String>();
for (String header : headers) {
String value = map.get(header) == null ? "" : map.get(header).replace(",", "");
items.add(value);
}
return StringUtils.join(items.toArray(), ",");
}
private Set<String> collectHeaders(List<Map<String, String>> flatJson) {
Set<String> headers = new TreeSet<String>();
for (Map<String, String> map : flatJson) {
headers.addAll(map.keySet());
}
return headers;
}
}
JSONtoCSV.class : which will use the above class to parse the json & write the key values as a .csv file
import java.util.List;
import java.util.Map;
public class JSONtoCSV {
public static void main(String[] args) throws Exception {
String jsonString = "{\n" +
"\"NAME\": \"Viv\",\n" +
"\"EMAIL\": \"lo\",\n" +
"\n" +
"\"PUBLIC_OFFICIALS_CONTACTED\": [{\"NAME_PUBLIC_OFFICIAL\": [ \"ff\"],\n" +
"\"TITLE_PUBLIC_OFFICIAL\": [\"ff\"]}],\n" +
"\n" +
"\"COMMUNICATION_TYPE\": [\"Meeting\",\"Phone\",\"Handout\",\"Conference\"],\n" +
"\n" +
"\"NAMES_OF_OTHERS_FROM_XXX\": [{\"NAME_OF_OTHERS\": [\"ff\"],\n" +
"\"TITLE_OF_OTHERS\": [ \"ff\"]}],\n" +
"\n" +
"\"COMMUNICATION_BENEFIT\": \"Yes\",\n" +
"\"AFFILIATE_NAME\": \"name\",\n" +
"\"COMMUNICATION_ARRANGED\": \"Yes, arranged by you\"\n" +
"}";
JsonFlattener parser = new JsonFlattener();
CSVWriter writer = new CSVWriter();
List<Map<String, String>> flatJson = parser.parseJson(jsonString);
writer.writeAsCSV(flatJson, "C:/sample.csv");
}
}

org.json.JSONException how can i clear this using volley library

Pls if any one know answer this question.
I have a error of JSONArray can't be converted in to JSONObject..
and I am new to using this volley library
JsonArrayRequest req = new JsonArrayRequest(URL,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Log.d(TAG, response.toString());
try {
// Parsing json array response
// loop through each json object
jsonResponse = "";
for (int i = 0; i < response.length(); i++) {
JSONArray product = (JSONArray) response
.get(i);
String productId = product.getString(Integer.parseInt("productId"));
String productName =product.getString(Integer.parseInt("productName"));
String productPrice = product.getString(Integer.parseInt("productPrice"));
String productImage =product.getString(Integer.parseInt("productImage"));
jsonResponse += "productId: " + productId + "\n\n";
jsonResponse += "productName: " + productName + "\n\n";
jsonResponse += "productPrice: " + productPrice + "\n\n";
jsonResponse += "productImage: " + productImage + "\n\n\n";
}
The response you are getting is a string and you are trying to assing it to jsonArray

How can I parse JSON in Windows Phone?

I would like to parse this page
That page has json data like this :
{"List":[{"num":"1","name":"hello","ox_score":"30","between_score":"30","order_score":"30","total_score":"90"}]}
I tried below code.(I used JSON.NET) but I was concerend about "List" and I also tried JArray and... o["Lists"]["name"] but I couldn't get a right results. The below code also return null messages.
Please help me out.
code
public void connection()
{
string uriString = "http://kah601.cafe24.com/jp_mango_loadboard.php";
WebClient wc = new WebClient();
wc.Headers["Accept"] = "application/json";
wc.DownloadStringCompleted += new DownloadStringCompletedEventHandler(wc_DownloadStringCompleted);
wc.DownloadStringAsync(new Uri(uriString));
}
void wc_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
JObject o = JObject.Parse(e.Result);
String name = (string) o["name"];
String ox_score = (string) o["ox_score"];
String between_score = (string) o["between_score"];
String order_score = (string) o["order_score"];
String total_score = (string) o["total_score"];
String rank_result = name + ox_score + between_score + order_score + total_score;
MessageBox.Show(rank_result);
}
Given it is a list, you should index the elements of the JArray. Here is a sample code to help you out (Notice the [0] => referencing the 1st element of the JArray):
void wc_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
JObject o = JObject.Parse(e.Result);
JArray a = (JArray)o["List"];
Debug.WriteLine("{0}", (String)a[0]["name"]);
}