I want to make a POST request to the Hubspot API (https://developers.hubspot.com/docs/methods/contacts/create_or_update) and I need the JSON to match this format:
{ "properties": [ { "property": "firstname", "value": "HubSpot" } ] }
Instead im getting this:
{ "properties": [ { "Key": "email", "Value": "alphatest#baconcompany.com" }, { "Key": "firstname", "Value": "testfirstname" } ] }
Instead of "property" and "value" , my code generates "Key" and "Value" , how can I change my JSON to match the right format?
Here is how I generate that dictionary:
public class HubspotContact
{
public Dictionary<string, string> properties { get; set; }
}
private static readonly HttpClient client = new HttpClient();
class DictionaryAsArrayResolver : DefaultContractResolver
{
protected override JsonContract CreateContract(Type objectType)
{
if (objectType.GetInterfaces().Any(i => i == typeof(IDictionary) ||
(i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IDictionary<,>))))
{
return base.CreateArrayContract(objectType);
}
return base.CreateContract(objectType);
}
}
And this is how I generate the JSON:
HubspotContact foo = new HubspotContact();
foo.properties = new Dictionary<string, string>();
foo.properties.Add("email", "alphatest#baconcompany.com");
foo.properties.Add("firstname", "firstname");
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.Formatting = Formatting.Indented;
settings.ContractResolver = new DictionaryAsArrayResolver();
string json = JsonConvert.SerializeObject(foo, settings);
Finally this is how I send my request:
var httpWebRequest =(HttpWebRequest)WebRequest.Create("https://api.hubapi.com/contacts/v1/contact/createOrUpdate/email/alphatest#baconcompany.com/?hapikey=myapikey");
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "POST";
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream())){
streamWriter.Write(json);
streamWriter.Flush();
streamWriter.Close();
}
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
Console.WriteLine(result.ToString());
}
Right now with the request as is I get this error:
System.Net.WebException: 'The remote server returned an error: (400) Bad Request.'
Change HubspotContact to this:
class PropertyValue
{
public string Property { get;set;}
public string Value { get;set;}
}
class HubspotContact
{
public List<PropertyValue> Properties {get;set;}
}
It should serialize to a proper format and it does not need custom serializer.
C#'s Json serializer does not support custom naming of properties coming from any generic data structure...
Try replacing the Dictionary with a custom class containing the properties "property" and "value" instead.
Related
I'm trying to write a function that wirte on my Json file the value I enter on PostMan
I have my Json file as following:
[
{
"targets":[
"192.168.1.101:9182",
"192.168.1.103:9100",
"192.168.1.105:9182"
]
}
]
M tried to for example a target with the following query:
{
"targets": [
"192.168.1.117:9100"
]
}
Here is my class model:
public class targetResponse
{
public IList<string> targets { get; set; }
}
using postman as shown in the picture:
Everything works fine in the part of prometheus (gives me no error).
Here is the function that I use:
[HttpPost]
[ProducesResponseType(typeof(targetResponse), StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<ActionResult<targetResponse>> PostNewInstanceToConfig([FromBody] targetResponse _target)
{
IList<targetResponse> myList = new List<targetResponse>();
var jsonString = System.IO.File
.ReadAllText(_filePath);
myList = JsonConvert.DeserializeObject<List<targetResponse>>(jsonString);
myList.FirstOrDefault().targets.Add(_target.ToString());
StreamWriter myWriter = new StreamWriter(_filePath);
JsonSerializer mySerializer = new JsonSerializer();
mySerializer.Serialize(myWriter, myList);
myWriter.Close();
return null;
}
It opens the file and write following thing, I dont understand why it doesnt why:
[
{
"targets": [
"192.168.1.101:9182",
"192.168.1.103:9100",
"192.168.1.105:9182",
"ApplicationTestCRUD_JSON.targetResponse",
"ApplicationTestCRUD_JSON.targetResponse"
]
}
]
The "ApplicationTestCRUD_JSON" is the name of my project.
Any help please?
EDIT:
I added a foreach loop and removed .toString() method, my function now looks like this:
[HttpPost]
[ProducesResponseType(typeof(targetResponse), StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<ActionResult<targetResponse>> PostNewInstanceToConfig([FromBody] targetResponse _target)
{
IList<targetResponse> myList = new List<targetResponse>();
var jsonString = System.IO.File
.ReadAllText(_filePath);
myList = JsonConvert.DeserializeObject<List<targetResponse>>(jsonString);
foreach(var x in _target.targets)
{
myList.FirstOrDefault().targets.Add(x);
}
StreamWriter myWriter = new StreamWriter(_filePath);
JsonSerializer mySerializer = new JsonSerializer();
mySerializer.Serialize(myWriter, myList);
myWriter.Close();
return null;
}
You are doing _target.ToString() and since _target is of type targetResponse you get the default ToString text back, which is the full name of the object type.
You probably want to access a property of _target instead.
I have a web api controller in .NET Core 2.1, which receives
JToken jsonBody
The json has the following structure
{
"id": "xxx",
"payload": {
"TelephoneNumber": "1111",
"Name": "Hans"
}
}
and more fields, but it's irrelevant.
I want to retrieve the Number and Name elegantly. Currently, I do the following, which I'm sure could be done in a nicer way:
var payload = JObject.Parse(jsonBody.SelectToken("Payload").ToString());
telephoneNumber = new TelephoneNumber(payload.SelectToken("TelephoneNumber").ToString());
I've tried just doing
jsonBody.SelectToken("Payload.TelephoneNumber")
but that doesn't work. I think that it's because somehow the jsonBody, that the controller receives, has only parsed the top nodes as json, hence it could be that it regards the value of
jsonBody.SelectToken("Payload")
as a string.
As per official documentation - you can do something like this:
var phone = jsonBody["payload"]["TelephoneNumber"].ToString();
var name = jsonBody["payload"]["Name"].ToString();
See a live demo on rextester.
This is at least a little bit more elegant:
var jsonBody = JObject.Parse(#"{
'id': 'xxx',
'payload': {
'TelephoneNumber': '1111',
'Name': 'Hans'
}
}");
var phone = jsonBody["payload"]["TelephoneNumber"].Value<string>();
var name = jsonBody["payload"]["Name"].Value<string>();
If you don't want to deserialize your full json, you can create a class with the properties you need
public class Payload
{
public string TelephoneNumber { get; set; }
public string Name { get; set; }
}
And then use JsonTextReader to deserialize the string:
private static Payload DeserializePayload(JToken token)
{
var serializer = new JsonSerializer();
using (JsonTextReader reader = new JsonTextReader(new StringReader(token.ToString())))
{
reader.CloseInput = true;
while (reader.Read())
{
if (reader.TokenType == JsonToken.StartObject && reader.Path.Equals("payload"))
{
var payload = serializer.Deserialize<Payload>(reader);
return payload;
}
}
}
// not found - return null? throw exception?
return null;
}
Testing the code:
var token = JToken.Parse(#"{
""id"": ""xxx"",
""payload"": {
""TelephoneNumber"": ""1111"",
""Name"": ""Hans""
}
}");
Payload payload = DeserializePayload(token);
Console.WriteLine($"Name: {payload.Name}, Phone number: {payload.TelephoneNumber}");
My code is below. When I post a JSON body that has \v in it, the server receives JSON that it cannot parse. Any help on how to make it work?
EDIT: well, the argument about my server not being able to parse it is weak, but http://jsonlint.com/ complains about it too. : )
in my emacs it looks like this:
{"key":"a^Kb"}
where ^K I think is a single character.
code:
using RestSharp;
using System;
using System.Collections.Generic;
namespace testapp
{
class Program
{
static void Main(string[] args)
{
var client = new RestClient();
var request = new RestRequest();
request.Method = Method.POST;
request.RequestFormat = DataFormat.Json;
request.Resource = "http://example.com/";
var data = new Dictionary<string, string>();
data.Add("key", "a\vb");
request.AddBody(data);
var response = client.Execute<Dictionary<string, string>>(request);
}
}
}
The default RestSharp JSON serializer serializes this as equivalent to the C# string "{\"key\":\"a\vb\"}"; that is, it sends the \v as a raw byte (0b) over the wire. This is why your server has trouble reading it. I'm unsure if this is legal JSON, but in any case there are ways to escape such a character to avoid issues.
I'd recommend using Json.NET to de/serialize your JSON. If you use the the following class (originally part of RestSharp) as your serializer, it will use Json.NET and should work correctly, since it will encode the \v as \u000b over the wire. The code (sans comments, and renamed for clarity) is copied here for reference:
public class JsonNetSerializer : ISerializer
{
private readonly Newtonsoft.Json.JsonSerializer _serializer;
public JsonNetSerializer()
{
ContentType = "application/json";
_serializer = new Newtonsoft.Json.JsonSerializer
{
MissingMemberHandling = MissingMemberHandling.Ignore,
NullValueHandling = NullValueHandling.Include,
DefaultValueHandling = DefaultValueHandling.Include
};
}
public JsonNetSerializer(Newtonsoft.Json.JsonSerializer serializer)
{
ContentType = "application/json";
_serializer = serializer;
}
public string Serialize(object obj)
{
using (var stringWriter = new StringWriter())
{
using (var jsonTextWriter = new JsonTextWriter(stringWriter))
{
jsonTextWriter.Formatting = Formatting.Indented;
jsonTextWriter.QuoteChar = '"';
_serializer.Serialize(jsonTextWriter, obj);
var result = stringWriter.ToString();
return result;
}
}
}
public string DateFormat { get; set; }
public string RootElement { get; set; }
public string Namespace { get; set; }
public string ContentType { get; set; }
}
To use it, add this line:
request.JsonSerializer = new JsonNetSerializer();
And it will serialize like:
{
"key": "a\u000bb"
}
Which is perfectly valid according to JSONLint.
I am using NewtonSoft.Json parser for parsing remote URL.
My remote JSON example as below
Kerberos.load({"todays" : "Fri, Mar 15",
"datas" : [
{
"id" : "2021200303"
}
]});
I am parsing JSON example as below
using (var WebClient = new System.Net.WebClient())
{
WebClient.Encoding = System.Text.Encoding.UTF8;
var _Json = WebClient.DownloadString(_MyJsonRemoteURL_);
_Json = _Json.Replace("Kerberos.load(", "");
_Json = _Json.Replace("]});", "]}");
dynamic _Dynamic = JsonConvert.DeserializeObject(_Json);
foreach (var _JsonNode in _Dynamic.datas)
{
MessageBox.Show(_JsonNode.SelectToken("id").ToString());
}
}
So, is there any way to validate remote JSON string, without using Replace method?
It's very much possible if you want to do it for JSON, check out Contract testing a json service in .net
cross posting the code here for quick reference, more detail checkout the link
[Test]
public void ShouldBeAbleToValidateTheJSONServiceResponseForFunctionalityA()
{
const string schemaJson = #"
{
'description': 'Service Response',
'type': 'object',
'properties': {
'product': {
'type': 'object',
'properties': {
'availability': {
'type': 'array',
'items': {
'type': 'object',
'properties': {
'Local': { 'type' : 'number'},
'Storehouse': { 'type' : 'number'},
}
}
}
}
}
}
}";
var parameters = new Dictionary<string, object> { { "id", 1 }, { "city", "Chennai" } };
AssertResponseIsValidSchema(schemaJson, parameters);
}
In one of my apps, I am getting the response from a webrequest. The service is Restful service and will return a result similar to the JSON format below:
{
"id" : "1lad07",
"text" : "test",
"url" : "http:\/\/twitpic.com\/1lacuz",
"width" : 220,
"height" : 84,
"size" : 8722,
"type" : "png",
"timestamp" : "Wed, 05 May 2010 16:11:48 +0000",
"user" : {
"id" : 12345,
"screen_name" : "twitpicuser"
}
}
and here is my current code:
byte[] bytes = Encoding.GetEncoding(contentEncoding).GetBytes(contents.ToString());
request.ContentLength = bytes.Length;
using (var requestStream = request.GetRequestStream()) {
requestStream.Write(bytes, 0, bytes.Length);
using (var twitpicResponse = (HttpWebResponse)request.GetResponse()) {
using (var reader = new StreamReader(twitpicResponse.GetResponseStream())) {
//What should I do here?
}
}
}
How can I read the response? I want the url and the username.
First you need an object
public class MyObject {
public string Id {get;set;}
public string Text {get;set;}
...
}
Then in here
using (var twitpicResponse = (HttpWebResponse)request.GetResponse()) {
using (var reader = new StreamReader(twitpicResponse.GetResponseStream())) {
JavaScriptSerializer js = new JavaScriptSerializer();
var objText = reader.ReadToEnd();
MyObject myojb = (MyObject)js.Deserialize(objText,typeof(MyObject));
}
}
I haven't tested with the hierarchical object you have, but this should give you access to the properties you want.
JavaScriptSerializer System.Web.Script.Serialization
I'd use RestSharp - https://github.com/restsharp/RestSharp
Create class to deserialize to:
public class MyObject {
public string Id { get; set; }
public string Text { get; set; }
...
}
And the code to get that object:
RestClient client = new RestClient("http://whatever.com");
RestRequest request = new RestRequest("path/to/object");
request.AddParameter("id", "123");
// The above code will make a request URL of
// "http://whatever.com/path/to/object?id=123"
// You can pick and choose what you need
var response = client.Execute<MyObject>(request);
MyObject obj = response.Data;
Check out http://restsharp.org/ to get started.
If you're getting source in Content
Use the following method
try
{
var response = restClient.Execute<List<EmpModel>>(restRequest);
var jsonContent = response.Content;
var data = JsonConvert.DeserializeObject<List<EmpModel>>(jsonContent);
foreach (EmpModel item in data)
{
listPassingData?.Add(item);
}
}
catch (Exception ex)
{
Console.WriteLine($"Data get mathod problem {ex} ");
}