I want to use facebook's API and i find it hard to convert objects to urlEncoded.
so, for now i have something like:
string postData = JsonConvert.SerializeObject(req);
postData = postData.Replace(#"\", "");
postData = HttpUtility.UrlEncode(postData);
byte[] data = Encoding.UTF8.GetBytes(postData);
string facebookUrl = "https://graph.facebook.com/v2.5/";
problem is that facebook doesn't accept jsons but UrlEncoded data, as it seems, correct me if im wrong.
So, Im pretty sure converting objects to UrlEncoded string is impossbile in .Net 4.5.1 because I've tried to use some of the answers for this questions that are while ago they are not working for me.
for example:
var result = new List<string>();
foreach (var property in TypeDescriptor.GetProperties(req))
{
result.Add(property.Name + "=" + property.GetValue(req));
}
postData = string.Join("&", result);
but .Name and .GetValue aren't defined at all.
Would like to get some help with that, TIA.
Objects i use:
internal sealed class FacebookValidationRequest
{
public string access_token;
public fbReq[] batch;
public string method;
public string format;
public int pretty;
public int suppress_http_code;
public string debug;
public FacebookValidationRequest(string appId, string userToken)
{
access_token = userToken;
batch = new[]
{
//test code
new fbReq("GET", "me"),
new fbReq("GET", "me/friends?limit=50") //,
//new fbReq("GET", "app?access_token=" + userToken)
};
method = "post";
format = "json";
pretty = 0;
suppress_http_code = 1;
debug = "all";
}
}
internal sealed class fbReq
{
public string method;
public string relative_url;
public fbReq(string m, string url)
{
method = m;
relative_url = url;
}
}
FacebookValidationRequest req = new FacebookValidationRequest(appToken, userToken);
Also, took the token for the facebook debugger site
how facebook wants to object to look like after encoding:
access_token=mytoken&batch=%5B%7B%22method%22%3A%22GET%22%2C%20%22relative_url%22%3A%22me%22%7D%2C%7B%22method%22%3A%22GET%22%2C%20%22relative_url%22%3A%22me%2Ffriends%3Flimit%3D50%22%7D%5D&debug=all&fields=id%2Cname&format=json&method=post&pretty=0&suppress_http_code=1
Seems to me that the easiest way to do this is with Attributes to describe your properties, just like how the .Net Json's DataContract system does it. Basically, you assign an attribute to each property you want serialized, and make that attribute contain the name to serialize it as. I don't think you want to get into the mess of actually writing your own DataContractSerializer, though, so it might be easier to simply create your own Property class and a simple serializer using reflection.
The attribute class:
[AttributeUsage(AttributeTargets.Property)]
public sealed class UrlEncodeAttribute : System.Attribute
{
public String Name { get; private set; }
public UrlEncodeAttribute(String name)
{
this.Name = name;
}
}
Then, to apply to your data class... put the attributes on all properties:
internal sealed class FacebookValidationRequest
{
[UrlEncodeAttribute("access_token")]
public String AccessToken { get; set; }
[UrlEncodeAttribute("method")]
public String Method { get; set; }
[UrlEncodeAttribute("format")]
public String Format { get; set; }
[UrlEncodeAttribute("pretty")]
public Int32 Pretty { get; set; }
[UrlEncodeAttribute("suppress_http_code")]
public Int32 SuppressHttpCode { get; set; }
[UrlEncodeAttribute("debug")]
public string Debug { get; set; }
public fbReq[] Batch { get; set; }
[UrlEncodeAttribute("batch")]
public String BatchString
{
get
{
// put your json serialization code here to return
// the contents of Batch as json string.
}
}
}
As you see, Batch does not have the UrlEncodeAttribute, while its string representation BatchString does. Its get is what will be called by the serializer, so you can put the conversion code in there.
Also note that thanks to the text names you give in the attributes, your properties don't need to have the names you actually get in the serialization, which looks much cleaner in my opinion. C#'s own serialization to xml and json works in the same way.
Now, let's take a look at the actual serialization, using reflection to get those properties:
public static String Serialize(Object obj, Boolean includeEmpty)
{
// go over the properties, see which ones have a UrlEncodeAttribute, and process them.
StringBuilder sb = new StringBuilder();
PropertyInfo[] properties = obj.GetType().GetProperties();
foreach (PropertyInfo p in properties)
{
object[] attrs = p.GetCustomAttributes(true);
foreach (Object attr in attrs)
{
UrlEncodeAttribute fldAttr = attr as UrlEncodeAttribute;
if (attr == null)
continue;
String objectName = fldAttr.Name;
Object objectDataObj = p.GetValue(obj, null);
String objectData = objectDataObj == null ? String.Empty : objectDataObj.ToString();
if (objectData.Length > 0 || includeEmpty)
{
objectData = HttpUtility.UrlEncode(objectData);
objectName= HttpUtility.UrlEncode(objectName);
if (sb.Length > 0)
sb.Append("&");
sb.Append(objectName).Append("=").Append(objectData);
}
break; // Only handle one UrlEncodeAttribute per property.
}
}
return sb.ToString();
}
A more advanced version of this could be made by including a serialization method property in the UrlEncodeAttribute class (probably best done with an enum), so you can simply specify to serialize the array on the fly using json. You'll obviously need to put the actual json converter into the Serialize function then. I thought using the getter on a dummy property as preparation method was simpler, here.
Obviously, calling it is simply this: (assuming here the Serialize() function is in a class called UrlEncodeSerializer)
FacebookValidationRequest fbreq = new FacebookValidationRequest();
// fill your data into fbreq here
// ...
// includeEmpty is set to true for testing here, but normally in
// UrlEncoded any missing property is just seen as empty anyway, so
// there should be no real difference.
String serialized = UrlEncodeSerializer.Serialize(fbreq, true);
Related
I've made a class containing everything from the json file.
Now I want to loop trough every object within this object so I can for fill the application with those values.
I want to scroll trough every CM0xx and use that description:
I hope my goal is clear with that screenshot.
I know that I have to do something like
foreach(CM0XX step in Stepsss)
but that simply wont work.
If making a list<string[]> for it is easier from a json but im clueless for the solution.
this is the code I have now. And the json file ive converted is generated so that should be fine.
string testdata = File.ReadAllText(Application.StartupPath + "\\TestData\\SSH.json");
Root JsonDecoded = JsonConvert.DeserializeObject<Root>(testdata);
testSteps Stepsss = JsonDecoded.SmartShoulder.TestSteps;
foreach (testSteps step in Stepsss)
{
}
this is part of the json. there are alot more CM012
public class CM181
{
public string Name;
public string description;
public string minValue;
public string maxValue;
public string unit;
public string instructions;
public string prerequisites;
}
public class Root
{
public kkkk kk;
}
public class kkkk
{
public string preset;
public testSteps TestSteps;
}
public class testSteps
{
public CM011 CM011;
}
You could use reflection to loop through the names and the values. If you just need the items under TestSteps, this should work. If you need a full hierarchy, that is a bit more involved. Here is an example below and the fiddle to it:
using System;
using System.Reflection;
public class Program
{
public static void Main()
{
var record = new Root()
{
Foo = "foo",
Bar = "bar"
};
PropertyInfo[] rootProperties = typeof(Record).GetProperties();
foreach (PropertyInfo property in rootProperties)
{
var value = property.GetValue(record);
Console.WriteLine(property.Name + " - " + value);
}
}
}
public class Root
{
public string Foo {get;set;}
public string Bar {get;set;}
}
Making a class to deserialize to is generally done to avoid the need to loop through all the properties. You've defined all the properties in the class, so you can just use them. It's a lot of overhead to use reflection to put all the values into a class, then again using reflection to pull them back out. That's why Newtonsoft has JToken/JObject/JArray classes.
using Newtonsoft.Json.Linq;
...
// parse your JSON
var jo = JObject.Parse(jsonString);
// go through all properties
// just for an example, I put them all in a dictionary
var dict = new Dictionary<String, JToken>()
foreach( JProperty p in jo.Properties() ) {
dict.Add(p.Name, p.Value)
}
Now, each Value is a JToken, which could actually be another JObject, or a JArray or just a simple token. You can check JToken.Type to see what type the property really has, and do something logical accordingly.
I am trying to use CSVHelper to serialize a database that is constructed out of multiple classes like shown below. I would like to make the csv a bit more human readable by adding information on units (when appropriate) and by ordering the data so that the "Name" always appears first. The rest can come in whatever order.
I have a class like shown below.
[DataContract(IsReference = true)]
public class OpaqueMaterial : LibraryComponent
{
[DataMember]
[Units("W/m.K")]
public double Conductivity { get; set; } = 2.4;
[DataMember]
public string Roughness { get; set; } = "Rough";
}
[DataContract]
public abstract class LibraryComponent
{
[DataMember, DefaultValue("No name")]
public string Name { get; set; } = "No name";
}
To avoid writing seprarate read write functions for each class I am reading and writing with templated functions like given below:
public void writeLibCSV<T>(string fp, List<T> records)
{
using (var sw = new StreamWriter(fp))
{
var csv = new CsvWriter(sw);
csv.WriteRecords(records);
}
}
public List<T> readLibCSV<T>(string fp)
{
var records = new List<T>();
using (var sr = new StreamReader(fp))
{
var csv = new CsvReader(sr);
records = csv.GetRecords<T>().ToList();
}
return records;
}
That I then use in the code to read and write as such:
writeLibCSV<OpaqueMaterial>(folderPath + #"\OpaqueMaterial.csv", lib.OpaqueMaterial.ToList());
List<OpaqueMaterial> inOpaqueMaterial = readLibCSV<OpaqueMaterial>(folderPath + #"\OpaqueMaterial.csv");
The CSV output then looks like:
Conductivity, Roughnes, Name
2.4, Rough, No Name
I would like to come out as:
Name, Conductivity [W/m.K], Roughness
No Name, 2.4, Rough
I know that the reordering is possible using maps like:
public class MyClassMap : ClassMap<OpaqueMaterial>
{
public MyClassMap()
{
Map(m => m.Name).Index(0);
AutoMap();
}
}
I would like to make this abstract so that I dont have to apply a different mapping to every class. I was not able to find an example that could help with adding the custom headers. Any suggestions or help would be greatly appreciated.
You could create a generic version of ClassMap<T> that will automatically inspect the type T using reflection and then construct the mapping dynamically based on the properties it finds and based on the attributes that may or may not be attached to it.
Without knowing the CsvHelper library too well, something like this should work:
public class AutoMap<T> : ClassMap<T>
{
public AutoMap()
{
var properties = typeof(T).GetProperties();
// map the name property first
var nameProperty = properties.FirstOrDefault(p => p.Name == "Name");
if (nameProperty != null)
MapProperty(nameProperty).Index(0);
foreach (var prop in properties.Where(p => p != nameProperty))
MapProperty(prop);
}
private MemberMap MapProperty(PropertyInfo pi)
{
var map = Map(typeof(T), pi);
// set name
string name = pi.Name;
var unitsAttribute = pi.GetCustomAttribute<UnitsAttribute>();
if (unitsAttribute != null)
name = $"{name} {unitsAttribute.Unit}";
map.Name(name);
// set default
var defaultValueAttribute = pi.GetCustomAttribute<DefaultValueAttribute>();
if (defaultValueAttribute != null)
map.Default(defaultValueAttribute.Value);
return map;
}
}
Now, you just need to create a AutoMap<T> for every type T that you want to support.
I’ve added examples for a UnitsAttribute and the DefaultValueAttribute, that should give you an idea on how to proceed with more attributes if you need more.
I have to store complex object into hash of redis cash.I am using stackexchange.redis to do this.My Class is like below.
public class Company
{
public string CompanyName { get; set; }
public List<User> UserList { get; set; }
}
public class User
{
public string Firstname { get; set; }
public string Lastname { get; set; }
public string Twitter { get; set; }
public string Blog { get; set; }
}
My code snippet to store data in redis is:
db.HashSet("Red:10000",comapny.ToHashEntries());
//Serialize in Redis format:
public static HashEntry[] ToHashEntries(this object obj)
{
PropertyInfo[] properties = obj.GetType().GetProperties();
return properties
.Where(x => x.GetValue(obj) != null) // <-- PREVENT NullReferenceException
.Select(property => new HashEntry(property.Name, property.GetValue(obj)
.ToString())).ToArray();
}
I could store the data in redis but not as i want.I am geting result as shown in below image.
I want UserList value in json format.So,how can i do this.
Probably the easiest path is checking if each property value is a collection (see the comments in my modified version of your method):
public static HashEntry[] ToHashEntries(this object obj)
{
PropertyInfo[] properties = obj.GetType().GetProperties();
return properties
.Where(x => x.GetValue(obj) != null) // <-- PREVENT NullReferenceException
.Select
(
property =>
{
object propertyValue = property.GetValue(obj);
string hashValue;
// This will detect if given property value is
// enumerable, which is a good reason to serialize it
// as JSON!
if(propertyValue is IEnumerable<object>)
{
// So you use JSON.NET to serialize the property
// value as JSON
hashValue = JsonConvert.SerializeObject(propertyValue);
}
else
{
hashValue = propertyValue.ToString();
}
return new HashEntry(property.Name, hashValue);
}
)
.ToArray();
}
It seems that there is something wrong with serializing. The best way of converting between JSON and .NET object is using the JsonSerializer:
JsonConvert.SerializeObject(fooObject);
You can see more details from Serializing and Deserializing JSON.
Also there is another good way,you can try to use IRedisTypedClient which is a part of ServiceStack.Redis.
IRedisTypedClient - A high-level 'strongly-typed' API available
on Service Stack's C# Redis Client to make all Redis Value operations
to apply against any c# type. Where all complex types are
transparently serialized to JSON using ServiceStack JsonSerializer -
The fastest JSON Serializer for .NET.
Hope this helps.
I love the way, how I can do this in Java. Simply with:
JSONObject obj = ...; // got by some procedure
String val_1 = obj.getString("attr_1");
int val_2 = obj.getInt("attr_2");
But I do not know whether there is something similar in C#. Doing type casting at every line of code is not something that I want. BTW. I'm using newtonsoft.json.
Okay, so in addition to #Kayani 's answer:
Let's assume you have the following json:
{
"AttributeOne":"TestString",
"AttributeTwo":1000
}
The corresponding class in C# would be this:
public class TestClass
{
public String AttributeOne { get; set; }
public Int32 AttributeTwo { get; set; }
}
So what you can do now is this:
TestClass obj = JsonConvert.DeserializeObject<TestClass>(str); //str = your json
String val_1 = obj.AttributeOne; //String
Int32 val_2 = obj.AttributeTwo; //Int
So you don't have to cast in every line.
If that still doesn't solve your problem, you could write some extensions like this:
public static class JObjectExtensions
{
public static string GetString(this JObject obj, string property)
{
return obj[property].ToString();
}
public static int GetInt(this JObject obj, string property)
{
return (int)obj[property];
}
}
And use them like this:
JObject obj = JObject.Parse(str); //str == your json
String val_1 = obj.GetString("attr_1");
int val_2 = obj.GetInt("attr_2");
//or you just use the built in methods
String val_1 = obj.Value<String>("AttributeOne");
int val_2 = obj.Value<int>("AttributeTwo");
For these snippets you need to import (using) Newtonsoft.Json and Newtonsoft.Json.Linq
Lets say you have a json string like the following:
{"question":"what is your name","A":"x","B":"y","C":"z","D":"a"}
Here we have a MCQ type question in the json string. Say we want to retrieve one of its property such as question. What we will do is that we create a class with the following properties:
question,A,B,C,D. Lets say the class is named MyQuestion we will just do the following:
MyQuestion myQuestion = JsonConvert.DerserializeObject<MyQuestion>(jsonString);
now you can access any property of the myQuestion object.
Ref: JsonConvert
I have some objects where some of the properties a URLEncoded.
What would be the fastest way to Uri.UnescapeDataString all properties on an object?
Not clear what you're going to reach. Just assuming you want to automate the process of decode and do not want to call each one property separately and decode it.
The way to iterate through class properties is reflection. Actually, reflection never was fast. But it's also not clear, what you mean by 'fastest'.
Here is a short sample how to achieve it with reflection:
public class DecoderTests
{
public String OneItem { get; set; }
public String SecondItem { get; set; }
public String ThirdClean { get; set; }
}
class Program
{
static void Main(string[] args)
{
var ddd = Uri.EscapeUriString("Http://google tes.com");
var decod = new DecoderTests
{
OneItem = ddd.ToString(),
SecondItem = ddd.ToString(),
ThirdClean = "clean"
};
PropertyInfo[] properties = typeof(DecoderTests).GetProperties();
foreach (PropertyInfo property in properties)
{
var current = property.GetValue(decod) as String;
if (!String.IsNullOrEmpty(current))
{
property.SetValue(decod, Uri.UnescapeDataString(current));
}
}
}
}
Or just call each property separately and decode it. All the alternatives for Uri.UnescapeDataString like Regex.Unescape or HttpUtility.UrlDecode will perform much slower.