Actually I've implmented ios in-app purchase & upon success, I receive json response.
The json response contains PurchaseToken, which is basically a base64 encoded javascript string.
{
"Id": "1000000872920320",
"TransactionDateUtc": "2021-09-06T14:42:17Z",
"ProductId": "1",
"AutoRenewing": false,
"PurchaseToken": "ewoJInNpZ25hdHVyZSIgPSAic29tZSBsb25nIGJhc2U2NCBzdHJpbmciOwoJInB1cmNoYXNlLWluZm8iID0gImV3b0pJbTl5YVdkcGJtRnNMWEIxY21Ob1lYTmxMV1JoZEdVdGNITjBJaUE5SUNJeU1EQXdMVEF4TFRBeElEQXhPakF4T2pBeElFRnRaWEpwWTJFdlRHOXpYMEZ1WjJWc1pYTWlPd29KSW5WdWFYRjFaUzFwWkdWdWRHbG1hV1Z5SWlBOUlDSnpiMjFsVlVsRUlqc0tDU0p2Y21sbmFXNWhiQzEwY21GdWMyRmpkR2x2YmkxcFpDSWdQU0FpVTI5dFpWUkpSQ0k3Q2draVluWnljeUlnUFNBaU15NDJJanNLQ1NKMGNtRnVjMkZqZEdsdmJpMXBaQ0lnUFNBaVUyOXRaVlJKUkNJN0Nna2ljWFZoYm5ScGRIa2lJRDBnSWpFaU93b0pJbWx1TFdGd2NDMXZkMjVsY25Ob2FYQXRkSGx3WlNJZ1BTQWlVRlZTUTBoQlUwVkVJanNLQ1NKdmNtbG5hVzVoYkMxd2RYSmphR0Z6WlMxa1lYUmxMVzF6SWlBOUlDSnpiMjFsSUc1MWJXVnlhV01nZEdsdFpTQnpkR0Z0Y0NCcGJpQnRjeUk3Q2draWRXNXBjWFZsTFhabGJtUnZjaTFwWkdWdWRHbG1hV1Z5SWlBOUlDSnpiMjFsSUZWSlJDSTdDZ2tpY0hKdlpIVmpkQzFwWkNJZ1BTQWlNU0k3Q2draWFYUmxiUzFwWkNJZ1BTQWljMjl0WlNCVmJtbHhkV1VnU1hSbGJTQkpSQ0k3Q2draWRtVnljMmx2YmkxbGVIUmxjbTVoYkMxcFpHVnVkR2xtYVdWeUlpQTlJQ0l3SWpzS0NTSnBjeTFwYmkxcGJuUnlieTF2Wm1abGNpMXdaWEpwYjJRaUlEMGdJbVpoYkhObElqc0tDU0p3ZFhKamFHRnpaUzFrWVhSbExXMXpJaUE5SUNKemIyMWxJRzUxYldWeWFXTWdkR2x0WlNCemRHRnRjQ0JwYmlCdGN5STdDZ2tpY0hWeVkyaGhjMlV0WkdGMFpTSWdQU0FpTWpBd01DMHdNUzB3TVNBd01Ub3dNVG93TVNCRmRHTXZSMDFVSWpzS0NTSnBjeTEwY21saGJDMXdaWEpwYjJRaUlEMGdJbVpoYkhObElqc0tDU0p2Y21sbmFXNWhiQzF3ZFhKamFHRnpaUzFrWVhSbElpQTlJQ0l5TURBd0xUQXhMVEF4SURBeE9qQXhPakF4SUVWMFl5OUhUVlFpT3dvSkltSnBaQ0lnUFNBaWFYQmhJR0Z3Y0NCaWRXNWtiR1VnYm1GdFpTSTdDZ2tpY0hWeVkyaGhjMlV0WkdGMFpTMXdjM1FpSUQwZ0lqSXdNREF0TURFdE1ERWdNREU2TURFNk1ERWdRVzFsY21sallTOU1iM05mUVc1blpXeGxjeUk3Q24wPSI7CgkiZW52aXJvbm1lbnQiID0gIlNhbmRib3giOwoJInBvZCIgPSAiMTAwIjsKCSJzaWduaW5nLXN0YXR1cyIgPSAiMCI7Cn0=",
"State": 0,
"ConsumptionState": 0,
"IsAcknowledged": false,
"Payload": null
}
I deserialize the above object & decode the base64 purchaseToken, but the decoded string is javascript string rather then json (look at the = & ;).
{
"signature" = "some long base64 string";
"purchase-info" = "ewoJIm9yaWdpbmFsLXB1cmNoYXNlLWRhdGUtcHN0IiA9ICIyMDAwLTAxLTAxIDAxOjAxOjAxIEFtZXJpY2EvTG9zX0FuZ2VsZXMiOwoJInVuaXF1ZS1pZGVudGlmaWVyIiA9ICJzb21lVUlEIjsKCSJvcmlnaW5hbC10cmFuc2FjdGlvbi1pZCIgPSAiU29tZVRJRCI7CgkiYnZycyIgPSAiMy42IjsKCSJ0cmFuc2FjdGlvbi1pZCIgPSAiU29tZVRJRCI7CgkicXVhbnRpdHkiID0gIjEiOwoJImluLWFwcC1vd25lcnNoaXAtdHlwZSIgPSAiUFVSQ0hBU0VEIjsKCSJvcmlnaW5hbC1wdXJjaGFzZS1kYXRlLW1zIiA9ICJzb21lIG51bWVyaWMgdGltZSBzdGFtcCBpbiBtcyI7CgkidW5pcXVlLXZlbmRvci1pZGVudGlmaWVyIiA9ICJzb21lIFVJRCI7CgkicHJvZHVjdC1pZCIgPSAiMSI7CgkiaXRlbS1pZCIgPSAic29tZSBVbmlxdWUgSXRlbSBJRCI7CgkidmVyc2lvbi1leHRlcm5hbC1pZGVudGlmaWVyIiA9ICIwIjsKCSJpcy1pbi1pbnRyby1vZmZlci1wZXJpb2QiID0gImZhbHNlIjsKCSJwdXJjaGFzZS1kYXRlLW1zIiA9ICJzb21lIG51bWVyaWMgdGltZSBzdGFtcCBpbiBtcyI7CgkicHVyY2hhc2UtZGF0ZSIgPSAiMjAwMC0wMS0wMSAwMTowMTowMSBFdGMvR01UIjsKCSJpcy10cmlhbC1wZXJpb2QiID0gImZhbHNlIjsKCSJvcmlnaW5hbC1wdXJjaGFzZS1kYXRlIiA9ICIyMDAwLTAxLTAxIDAxOjAxOjAxIEV0Yy9HTVQiOwoJImJpZCIgPSAiaXBhIGFwcCBidW5kbGUgbmFtZSI7CgkicHVyY2hhc2UtZGF0ZS1wc3QiID0gIjIwMDAtMDEtMDEgMDE6MDE6MDEgQW1lcmljYS9Mb3NfQW5nZWxlcyI7Cn0=";
"environment" = "Sandbox";
"pod" = "100";
"signing-status" = "0";
}
And the purchase info:
{
"original-purchase-date-pst" = "2000-01-01 01:01:01 America/Los_Angeles";
"unique-identifier" = "someUID";
"original-transaction-id" = "SomeTID";
"bvrs" = "3.6";
"transaction-id" = "SomeTID";
"quantity" = "1";
"in-app-ownership-type" = "PURCHASED";
"original-purchase-date-ms" = "some numeric time stamp in ms";
"unique-vendor-identifier" = "some UID";
"product-id" = "1";
"item-id" = "some Unique Item ID";
"version-external-identifier" = "0";
"is-in-intro-offer-period" = "false";
"purchase-date-ms" = "some numeric time stamp in ms";
"purchase-date" = "2000-01-01 01:01:01 Etc/GMT";
"is-trial-period" = "false";
"original-purchase-date" = "2000-01-01 01:01:01 Etc/GMT";
"bid" = "ipa app bundle name";
"purchase-date-pst" = "2000-01-01 01:01:01 America/Los_Angeles";
}
I'm facing this issue with deserializing of the javascript string into a C# object.
Any proper way to handle this deserialization?
Newtonsoft.Json is not able to handle it & I have looked its docs again & again to find any suitable methods but no success.
Is there any way other then to replace characters & make its json like?
Any help would be highly appreciated.
As others already mentioned, it's not JSON. But based on the example you provided you should be able to transform it to a readable JSON. It's not the most pretty solution, but it seems to work. It have some draw-backs:
It will only work when " = " is the separator.
It will only work when each field is separated by ; followed by line-break (windows-style).
private string MakeReadableJson(string base64Input)
{
var data = System.Convert.FromBase64String(base64Input);
string readableString = Encoding.UTF8.GetString(data);
var json = readableString.Replace("\" = \"", "\":\"").Replace(";\n", ",");
return json;
}
I use System.Text.JsonSerializer. Use it like so:
string json = #"{
""Id"": ""1000000872920320"",
""TransactionDateUtc"": ""2021-09-06T14:42:17Z"",
""ProductId"": ""1"",
""AutoRenewing"": false,
""PurchaseToken"": ""ewoJInNpZ25hdHVyZSIgPSAic29tZSBsb25nIGJhc2U2NCBzdHJpbmciOwoJInB1cmNoYXNlLWluZm8iID0gImV3b0pJbTl5YVdkcGJtRnNMWEIxY21Ob1lYTmxMV1JoZEdVdGNITjBJaUE5SUNJeU1EQXdMVEF4TFRBeElEQXhPakF4T2pBeElFRnRaWEpwWTJFdlRHOXpYMEZ1WjJWc1pYTWlPd29KSW5WdWFYRjFaUzFwWkdWdWRHbG1hV1Z5SWlBOUlDSnpiMjFsVlVsRUlqc0tDU0p2Y21sbmFXNWhiQzEwY21GdWMyRmpkR2x2YmkxcFpDSWdQU0FpVTI5dFpWUkpSQ0k3Q2draVluWnljeUlnUFNBaU15NDJJanNLQ1NKMGNtRnVjMkZqZEdsdmJpMXBaQ0lnUFNBaVUyOXRaVlJKUkNJN0Nna2ljWFZoYm5ScGRIa2lJRDBnSWpFaU93b0pJbWx1TFdGd2NDMXZkMjVsY25Ob2FYQXRkSGx3WlNJZ1BTQWlVRlZTUTBoQlUwVkVJanNLQ1NKdmNtbG5hVzVoYkMxd2RYSmphR0Z6WlMxa1lYUmxMVzF6SWlBOUlDSnpiMjFsSUc1MWJXVnlhV01nZEdsdFpTQnpkR0Z0Y0NCcGJpQnRjeUk3Q2draWRXNXBjWFZsTFhabGJtUnZjaTFwWkdWdWRHbG1hV1Z5SWlBOUlDSnpiMjFsSUZWSlJDSTdDZ2tpY0hKdlpIVmpkQzFwWkNJZ1BTQWlNU0k3Q2draWFYUmxiUzFwWkNJZ1BTQWljMjl0WlNCVmJtbHhkV1VnU1hSbGJTQkpSQ0k3Q2draWRtVnljMmx2YmkxbGVIUmxjbTVoYkMxcFpHVnVkR2xtYVdWeUlpQTlJQ0l3SWpzS0NTSnBjeTFwYmkxcGJuUnlieTF2Wm1abGNpMXdaWEpwYjJRaUlEMGdJbVpoYkhObElqc0tDU0p3ZFhKamFHRnpaUzFrWVhSbExXMXpJaUE5SUNKemIyMWxJRzUxYldWeWFXTWdkR2x0WlNCemRHRnRjQ0JwYmlCdGN5STdDZ2tpY0hWeVkyaGhjMlV0WkdGMFpTSWdQU0FpTWpBd01DMHdNUzB3TVNBd01Ub3dNVG93TVNCRmRHTXZSMDFVSWpzS0NTSnBjeTEwY21saGJDMXdaWEpwYjJRaUlEMGdJbVpoYkhObElqc0tDU0p2Y21sbmFXNWhiQzF3ZFhKamFHRnpaUzFrWVhSbElpQTlJQ0l5TURBd0xUQXhMVEF4SURBeE9qQXhPakF4SUVWMFl5OUhUVlFpT3dvSkltSnBaQ0lnUFNBaWFYQmhJR0Z3Y0NCaWRXNWtiR1VnYm1GdFpTSTdDZ2tpY0hWeVkyaGhjMlV0WkdGMFpTMXdjM1FpSUQwZ0lqSXdNREF0TURFdE1ERWdNREU2TURFNk1ERWdRVzFsY21sallTOU1iM05mUVc1blpXeGxjeUk3Q24wPSI7CgkiZW52aXJvbm1lbnQiID0gIlNhbmRib3giOwoJInBvZCIgPSAiMTAwIjsKCSJzaWduaW5nLXN0YXR1cyIgPSAiMCI7Cn0="",
""State"": 0,
""ConsumptionState"": 0,
""IsAcknowledged"": false,
""Payload"": null
}";
var info = JsonSerializer.Deserialize<ResultFromApple>(json);
var purchaseTokenJson = MakeReadableJson(info.PurchaseToken);
PurchaseToken purchaseToken = JsonSerializer.Deserialize<PurchaseToken>(purchaseTokenJson, new JsonSerializerOptions()
{
AllowTrailingCommas = true
});
var purchaseInfoJson = MakeReadableJson(purchaseToken.PurchaseInfo);
PurchaseInfo purchaseInfo = JsonSerializer.Deserialize<PurchaseInfo>(purchaseInfoJson, new JsonSerializerOptions()
{
AllowTrailingCommas = true
});
And your models:
public class PurchaseToken
{
public string signature { get; set; }
[JsonPropertyName("purchase-info")]
public string PurchaseInfo { get; set; }
public string environment { get; set; }
public string pod { get; set; }
[JsonPropertyName("signing-status")]
public string SigningStatus { get; set; }
}
public class ResultFromApple
{
public string Id { get; set; }
public DateTime TransactionDateUtc { get; set; }
public string ProductId { get; set; }
public bool AutoRenewing { get; set; }
public string PurchaseToken { get; set; }
public int State { get; set; }
public int ConsumptionState { get; set; }
public bool IsAcknowledged { get; set; }
public object Payload { get; set; }
}
public class PurchaseInfo
{
[JsonPropertyName("original-purchase-date-pst")]
public string OriginalPurchaseDatePst { get; set; }
[JsonPropertyName("unique-identifier")]
public string UniqueIdentifier { get; set; }
[JsonPropertyName("original-transaction-id")]
public string OriginalTransactionId { get; set; }
public string bvrs { get; set; }
[JsonPropertyName("transaction-id")]
public string TransactionId { get; set; }
public string quantity { get; set; }
[JsonPropertyName("in-app-ownership-type")]
public string InAppOwnershipType { get; set; }
[JsonPropertyName("original-purchase-date-ms")]
public string OriginalPurchaseDateMs { get; set; }
[JsonPropertyName("unique-vendor-identifier")]
public string UniqueVendorIdentifier { get; set; }
[JsonPropertyName("product-id")]
public string ProductId { get; set; }
[JsonPropertyName("item-id")]
public string ItemId { get; set; }
[JsonPropertyName("version-external-identifier")]
public string VersionExternalIdentifier { get; set; }
[JsonPropertyName("is-in-intro-offer-period")]
public string IsInIntroOfferPeriod { get; set; }
[JsonPropertyName("purchase-date-ms")]
public string PurchaseDateMs { get; set; }
[JsonPropertyName("purchase-date")]
public string PurchaseDate { get; set; }
[JsonPropertyName("is-trial-period")]
public string IsTrialPeriod { get; set; }
[JsonPropertyName("original-purchase-date")]
public string OriginalPurchaseDate { get; set; }
public string bid { get; set; }
[JsonPropertyName("purchase-date-pst")]
public string PurchaseDatePst { get; set; }
}
I would use Pidgin to parse something like this.
Here's some code that parses your data into a Dictionary<string, string> and prints out the results:
using System;
using System.Collections.Generic;
using System.Linq;
using Pidgin;
using static Pidgin.Parser;
namespace NotQuiteJsonParsing
{
class Program
{
const string PurchaseInfo = #"{
""original-purchase-date-pst"" = ""2000-01-01 01:01:01 America/Los_Angeles"";
""unique-identifier"" = ""someUID"";
""original-transaction-id"" = ""SomeTID"";
""bvrs"" = ""3.6"";
""transaction-id"" = ""SomeTID"";
""quantity"" = ""1"";
""in-app-ownership-type"" = ""PURCHASED"";
""original-purchase-date-ms"" = ""some numeric time stamp in ms"";
""unique-vendor-identifier"" = ""some UID"";
""product-id"" = ""1"";
""item-id"" = ""some Unique Item ID"";
""version-external-identifier"" = ""0"";
""is-in-intro-offer-period"" = ""false"";
""purchase-date-ms"" = ""some numeric time stamp in ms"";
""purchase-date"" = ""2000-01-01 01:01:01 Etc/GMT"";
""is-trial-period"" = ""false"";
""original-purchase-date"" = ""2000-01-01 01:01:01 Etc/GMT"";
""bid"" = ""ipa app bundle name"";
""purchase-date-pst"" = ""2000-01-01 01:01:01 America/Los_Angeles"";
}";
private static string IEnumerableCharToString(IEnumerable<char> value)
{
// Feel free to swap this with an alternative answer to https://stackoverflow.com/questions/8108313
return new string(value.ToArray());
}
// Parsers can be slow to build, so minimise the
// number of times this setup method is called. See
// https://github.com/benjamin-hodgson/Pidgin#speed-tips
private static Parser<char, Dictionary<string, string>> BuildBlockParser()
{
var stringParser = Char('"').Then(AnyCharExcept('"').AtLeastOnceUntil(Char('"')));
var lineParser = Map(
(key, value) => new KeyValuePair<string, string>(IEnumerableCharToString(key), IEnumerableCharToString(value)),
stringParser.Before(SkipWhitespaces).Before(Char('=')).Before(SkipWhitespaces),
stringParser.Before(SkipWhitespaces).Before(Char(';')).Before(SkipWhitespaces));
var linesParser = lineParser.AtLeastOnce().Map(pairs => new Dictionary<string, string>(pairs));
var blockParser = SkipWhitespaces.Then(Char('{')).Then(SkipWhitespaces).Then(linesParser).Before(Char('}'));
return blockParser;
}
static void Main()
{
var blockParser = BuildBlockParser();
var result = blockParser.ParseOrThrow(PurchaseInfo);
foreach (var (key, value) in result)
{
Console.WriteLine($"{key} = {value}");
}
}
}
}
This parser has the following limitations:
Values in key-value pairs are always strings, not numbers, booleans or anything else.
There is no support for escaped " characters in keys or values. I don't know how they would be escaped.
There is no support for escape sequences such as \r, \n, \t or \u0123.
It's a bit embarrassing. I saw the problem as the opposite before. Try this, I think this can meet the needs:
Parse JavaScript string
static void Main(string[] args)
{
var jsStr = #"{
""signature"" = ""some long base64 string"";
""purchase-info"" = ""ewoJIm9yaWdpbmFsLXB1cmNoYXNlLWRhdGUtcHN0IiA9ICIyMDAwLTAxLTAxIDAxOjAxOjAxIEFtZXJpY2EvTG9zX0FuZ2VsZXMiOwoJInVuaXF1ZS1pZGVudGlmaWVyIiA9ICJzb21lVUlEIjsKCSJvcmlnaW5hbC10cmFuc2FjdGlvbi1pZCIgPSAiU29tZVRJRCI7CgkiYnZycyIgPSAiMy42IjsKCSJ0cmFuc2FjdGlvbi1pZCIgPSAiU29tZVRJRCI7CgkicXVhbnRpdHkiID0gIjEiOwoJImluLWFwcC1vd25lcnNoaXAtdHlwZSIgPSAiUFVSQ0hBU0VEIjsKCSJvcmlnaW5hbC1wdXJjaGFzZS1kYXRlLW1zIiA9ICJzb21lIG51bWVyaWMgdGltZSBzdGFtcCBpbiBtcyI7CgkidW5pcXVlLXZlbmRvci1pZGVudGlmaWVyIiA9ICJzb21lIFVJRCI7CgkicHJvZHVjdC1pZCIgPSAiMSI7CgkiaXRlbS1pZCIgPSAic29tZSBVbmlxdWUgSXRlbSBJRCI7CgkidmVyc2lvbi1leHRlcm5hbC1pZGVudGlmaWVyIiA9ICIwIjsKCSJpcy1pbi1pbnRyby1vZmZlci1wZXJpb2QiID0gImZhbHNlIjsKCSJwdXJjaGFzZS1kYXRlLW1zIiA9ICJzb21lIG51bWVyaWMgdGltZSBzdGFtcCBpbiBtcyI7CgkicHVyY2hhc2UtZGF0ZSIgPSAiMjAwMC0wMS0wMSAwMTowMTowMSBFdGMvR01UIjsKCSJpcy10cmlhbC1wZXJpb2QiID0gImZhbHNlIjsKCSJvcmlnaW5hbC1wdXJjaGFzZS1kYXRlIiA9ICIyMDAwLTAxLTAxIDAxOjAxOjAxIEV0Yy9HTVQiOwoJImJpZCIgPSAiaXBhIGFwcCBidW5kbGUgbmFtZSI7CgkicHVyY2hhc2UtZGF0ZS1wc3QiID0gIjIwMDAtMDEtMDEgMDE6MDE6MDEgQW1lcmljYS9Mb3NfQW5nZWxlcyI7Cn0="";
""environment"" = ""Sandbox"";
""pod"" = ""100"";
""signing-status"" = ""0"";
}";
var model = GetModelFromJsStr<PurchaseToken>(jsStr);
}
public class PurchaseToken
{
[JsonPropertyName("signature")]
public string Signature { get; set; }
[JsonPropertyName("purchase-info")]
public string PurchaseInfo { get; set; }
[JsonPropertyName("environment")]
public string Environment { get; set; }
[JsonPropertyName("pod")]
public int Pod { get; set; }
[JsonPropertyName("signing-status")]
public int SigningStatus { get; set; }
}
public static T GetModelFromJsStr<T>(string jsStr) where T : new()
{
var model = new T();
var rows = jsStr.Split("\n").Select(item => item.Trim()).ToList();
foreach (var prop in typeof(T).GetProperties())
{
var jsonProperty = prop.GetCustomAttribute<JsonPropertyNameAttribute>();
if (jsonProperty != null)
{
var matchRow = rows.FirstOrDefault(row => row.StartsWith(#$"""{jsonProperty.Name}"" ="));
if (matchRow != null)
{
var pattern = #$"^""{jsonProperty.Name}"" = ""(.*)"";$";
var match = Regex.Match(matchRow, pattern);
if (match?.Groups?.Count > 1)
{
// convertible types can be extended
if (prop.PropertyType == typeof(int))
{
int.TryParse(match.Groups[1].Value, out var propValue);
prop.SetValue(model, propValue);
}
else
{
prop.SetValue(model, match.Groups[1].Value);
}
}
}
}
};
return model;
}
Was able to handle this by with following code using Newtonsoft.Json.JsonConverter:
Create models for the data
public class InAppPurchaseToken
{
public string Signature { get; set; }
[JsonProperty("purchase-info")]
public string PurchaseInfo { get; set; }
public string Environment { get; set; }
public string Pod { get; set; }
public string SigningStatus { get; set; }
}
public class InAppPurchaseInfo
{
[JsonProperty("original-purchase-date-pst")]
public string originalpurchasedatepst { get; set; }
[JsonProperty("unique-identifier")]
public string uniqueidentifier { get; set; }
[JsonProperty("original-transaction-id")]
public string originaltransactionid { get; set; }
public string bvrs { get; set; }
[JsonProperty("transaction-id")]
public string transactionid { get; set; }
public string quantity { get; set; }
[JsonProperty("in-app-ownership-type")]
public string inappownershiptype { get; set; }
[JsonProperty("original-purchase-date-ms")]
public string originalpurchasedatems { get; set; }
[JsonProperty("unique-vendor-identifier")]
public string uniquevendoridentifier { get; set; }
[JsonProperty("product-id")]
public string productid { get; set; }
[JsonProperty("item-id")]
public string itemid { get; set; }
[JsonProperty("version-external-identifier")]
public string versionexternalidentifier { get; set; }
[JsonProperty("is-in-intro-offer-period")]
public string isinintroofferperiod { get; set; }
[JsonProperty("purchase-date-ms")]
public string purchasedatems { get; set; }
[JsonProperty("purchase-date")]
public string purchasedate { get; set; }
[JsonProperty("is-trial-period")]
public string istrialperiod { get; set; }
[JsonProperty("original-purchase-date")]
public string originalpurchasedate { get; set; }
public string bid { get; set; }
[JsonProperty("purchase-date-pst")]
public string purchasedatepst { get; set; }
}
And the handle the parsing using following code (assuming you have deserialized the initial json as inAppPayData C# object):
public string GetJsonFromBase64JsStr(string base64JsStr)
{
if (string.IsNullOrWhiteSpace(base64JsStr))
return "";
var decodedStr2Parse = Encoding.UTF8.GetString(Convert.FromBase64String(base64JsStr));
//var ConvertedJsonStrComplete = decodedStr2Parse.Replace("\" = \"", "\":\"").Replace(";\n", ",").Replace(",}", "}"); //more error prone
var ConvertedJsonStrPartial = decodedStr2Parse.Replace("\" = \"", "\":\"").Replace(";\n", ",");
var ConvertedJsonStrComplete = ConvertedJsonStrPartial.Remove(ConvertedJsonStrPartial.LastIndexOf(",}"), 1);
return ConvertedJsonStrComplete;
}
//call the above function with base64JsString
var purchaseJsonStr = GetJsonFromBase64JsStr(inAppPayData.PurchaseToken);
var purchaseTokenObj = JsonConvert.DeserializeObject<InAppPurchaseToken>(purchaseJsonStr);
var purchaseInfoJsonStr = GetJsonFromBase64JsStr(purchaseTokenObj.PurchaseInfo);
var purchaseInfoObj = JsonConvert.DeserializeObject<InAppPurchaseInfo>(purchaseInfoJsonStr);
Related
This is my javascript to load partial view by sending a data array as a parameter.
$('body').on('click', '.btn-add-answer', function () {
var answerObj = Array.from(GetAnswerDetails(this));
var lastAnswer = answerObj[answerObj.length - 1];
var answers = {};
answers.Id = parseInt(lastAnswer.Id) + 1;
answers.FormQuestionId = lastAnswer.FormQuestionId;
answers.Text = "";
answers.IsCorrect = false;
answers.Score = null;
answers.QuestionAnswerId = 0;
answers.Sequence = 0;
answerObj.push(answers);
$("#survey-answer-container")
.load("LoadTest", answerObj);
});
This is my controller
public ActionResult LoadTest(List<AnswerDto> answers)
{
return PartialView("_SurveyPageSectionQuestionAnswer", answers);
}
And this is my DTO
public class AnswerDto
{
public int Id { get; set; }
public string Text { get; set; }
public int Sequence { get; set; }
public bool? IsCorrect { get; set; }
public int? Score { get; set; }
public int FormQuestionId { get; set; }
public int QuestionAnswerId { get; set; }
}
The issue is the parameter didn't get to the controller. The 'answers' parameter in the controller will only have default values.
How to send data array from javascript as a parameter in partial view load?
Try your object like below. Wrap your object as { answers: answerObj } so it could match with parameter name.
$("#survey-answer-container")
.load("LoadTest", { answers: answerObj });
There's a javascript library called Crypto-js and i'm trying to convert some methods I use to c#.
For example in javascript:
var payload = JSON.stringify({ market: "BTC-ETH", order: { price: "0.02159338", side: "buy", size: "0.024" } });
var contentHash = cryptoJS.SHA512(payload).toString(cryptoJS.enc.Hex);
console.log(contentHash);
In C#
public class OrdersVM
{
public string Market { get; set; }
public Order Order { get; set; }
}
public class Order
{
public string Price { get; set; }
public string Side { get; set; }
public string Size { get; set; }
}
public async Task<IActionResult> Orders([FromBody] OrdersVM vm) {
var payload = JsonConvert.SerializeObject(vm);
var contentHash = sha512Hex(payload).ToLower();
Console.WriteLine(contentHash);
}
public string sha512Hex(string input)
{
var bytes = Encoding.UTF8.GetBytes(input);
using (var hash = SHA512.Create())
{
hash.ComputeHash(bytes);
return BitConverter.ToString(hash.Hash).Replace("-", "");
}
}
contentHash for javascript is
"99bb05af8aace509189e08625bb4e475a9daaafc92edf5c85fa1aefcc16c16e4533c23843c5806aef01c97e8cb4150b2dc129d04d3b6a50331833fe5cb8158fc"
and for c#
"731b92cf482ff90ffe759e356959ec005334062bdc3c2cc78b48c3041d21a45ecaa6b33f6df2971fa868f94f04b7596e818104cb1017ed1c436365beac3a01d1"
What am I doing wrong with c# conversion?
The issue is that JSON.Net, by default, will serialise your property names exactly as the appear, meaning they all start with a capital letter. There are two ways to fix this:
Using JsonProperty to explicitly control the property name serialisation. For example:
public class OrdersVM
{
[JsonProperty("market")]
public string Market { get; set; }
[JsonProperty("order")]
public Order Order { get; set; }
}
Use a contract resolver to tell JSON.Net how to process the names. Fortunately there is one provided for you that will do this:
var settings = new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
}
var payload = JsonConvert.SerializeObject(vm, settings);
This question already has answers here:
Parse JSON array in JSON.NET
(3 answers)
Closed 5 years ago.
I have regex expression, which prevented me entering certain characters in the input field
onKeyMonitor ($event) {
const value = $event.key;
const pattern = /^[#$^<>[\]{}]*$/;
const regex = new RegExp(pattern);
if (regex.test(value)) {
$event.preventDefault();
}
}
But this is failing if I paste the same special characters, What needs to be done here.
I have written an onpaste event as well. with similar logic, but it is failing.
Initially you could define the following classes:
public class AnswerOption
{
[JsonProperty("parentQuestion")]
public string ParentQuestion { get; set; }
[JsonProperty("parentAnswer")]
public object ParentAnswer { get; set; }
[JsonProperty("answerOption")]
public object Option { get; set; }
}
public class Question
{
[JsonProperty("questionId")]
public int QuestionId { get; set; }
[JsonProperty("questionName")]
public string QuestionName { get; set; }
[JsonProperty("questionType")]
public string QuestionType { get; set; }
[JsonProperty("questionSequenceNumber")]
public int QuestionSequenceNumber { get; set; }
[JsonProperty("pageNo")]
public int PageNo { get; set; }
[JsonProperty("highlightedText")]
public string HighlightedText { get; set; }
[JsonProperty("isDynamicText")]
public string IsDynamicText { get; set; }
[JsonProperty("answerOptions")]
public IList<AnswerOption> AnswerOptions { get; set; }
}
public class DataObj
{
[JsonProperty("surveyId")]
public int SurveyId { get; set; }
[JsonProperty("questions")]
public IList<Question> Questions { get; set; }
}
public class Example
{
[JsonProperty("dataObj")]
public DataObj DataObj { get; set; }
[JsonProperty("errorCode")]
public int ErrorCode { get; set; }
[JsonProperty("errorMessage")]
public string ErrorMessage { get; set; }
}
Then you could deserialize your json as below:
var example = JsonConvert.DeserializeObject<Example>(json);
where json is a variable that holds the json you want to deserialize.
Last you could access the firsts question id as below:
labl1.text = example.DataObj?.Questions?.FirstOrDefault()?.QuestionId;
Use this website to help you generate C# classes from Json string http://json2csharp.com/
Note: Don't forget to double the data type.
image
In the image link above I have created a form which can dynamically add more rows of input fields
The values from the input field that are dynamically added are pushed into an array while the values on the green part are place into a javascript object.
reservations.push({ Day:d, Room: r, TimeIn: datetimeIn.toString(), TimeOut: datetimeOut.toString()});//this is assuming that only 1 row of input field was added
var r = JSON.stringify(reservations);
//There's only 1 course, description, section, datefrom and dateto while there can be many Day, Room, TimeIn, TimeOut.
var reservation = { CourseCode: courseCode.val(), Description: description.val(), Section: section.val(), DateFrom: dateF, DateTo: dateT, r };
$.ajax({
url: '/ReserveSubject',
type: 'POST',
data: 'reservation=' + JSON.stringify(reservation),
How do I take the values of the json string and create and instance of an object that will take those values
[HttpPost]
public ActionResult ReserveSubject(string reservation)
{
Subject sub = new Subject();
sub.CourseCode = reservation.CourseCode;
sub.Description = reservationDescription;
.
.
.
//loop through reservation data from dynamically added rows of input field
{
Schedule sch = new Schedule();
sch.Day = reservation.Day;
sch.Room = reservation.Room;
.
.
.
sub.Schedule.add(sch);
}
sub.ScheduleTable = MethodThatWillConvertScheduleListToDatatable(sub.Schedule);
}
Object to instantiate
public class Subject
{
string CourseCode { get; set; }
string Description { get; set; }
string Section { get; set; }
string DateFrom { get; set; }
string DateTo { get; set; }
List<Schedule> Schedule { get; set; }
DataTable ScheduleTable { get; set; }
}
public class Schedule
{
string Day { get; set; }
string Room { get; set; }
string TimeIn { get; set; }
string Timeout { get; set; }
}
I have already downloaded NewtonSoft as i think most of your answer will make use of it.
var jsonObject = {
"Prop1" : "something",
"Prop2" : "something",
"Prop3List" : GetSomeJsonScheduleList()
etc...
};
public class ExampleModel
{
public string Prop1 {get; set;}
public string Prop2 {get; set;}
public IList<Schedule> Prop3List {get; set;}
}
public ActionResult ControllerMethod(ExampleModel model)
{
//Use your model like normal
}
Then just JSON.stringify(jsonObject) in your ajax call.
Take note of the naming conventions.
This question already has an answer here:
How to get the values from the Model and into Views Javascript (Visual Studio 2015 mvc)
(1 answer)
Closed 6 years ago.
How do I set a list of objects coming from my viewmodel to a javascript variable to use in my js file? I'm getting an error when I try to set it.
Here is my viewmodel
public class TargetListAddressesViewModel
{
public List<Address> Addresses { get; set; }
public int OrganizationId { get; set; }
}
Here is the address object
public partial class Address
{
[Column] public int AddressId { get; set; }
[Column] public bool IsPrimary { get; set; }
[Column] public int ParentId { get; set; }
[Column] public int ParentTypeId { get; set; }
[Column] public int AddressTypeId { get; set; }
[Column] public string Address1 { get; set; }
[Column] public string Address2 { get; set; }
[Column] public string City { get; set; }
[Column] public string State { get; set; }
[Column] public string PostalCode { get; set; }
[Column] public string Country { get; set; }
[Column] public string AddressHash { get; set; }
[Column] public decimal Latitude { get; set; }
[Column] public decimal Longitude { get; set; }
[Column] public string ModifiedBy { get; set; }
}
Here is where I try and set it to a js variable, but it throws an error that says "VM320917:3 Uncaught SyntaxError: Unterminated template literal"
<script type="text/javascript">
var organizationId = #Html.Raw(Model.OrganizationId);
var addresses = #Html.Raw(Model.Addresses);
</script>
var addresses = #Html.Raw(Json.Encode(Model.Addresses))