3

I am writing a program in json-rpc and I want to declare string variable in json string i am doing mistake while declaring it dont know what is the correct format for that is there anybody who can solve this problem.

(string amnt= "1000000" I want to declare it in json amount in single quotes)

string amnt = "100000000";
        string json = @"
        {
'method': 'submit',
'params': [{
    'secret': 'snL7AcZbKsHm1H7VjeZg7gNS55Xkd',
    'tx_json': {
        'Account': 'rHSqhmuevNJg9ZYpspYHNnQDxraozuCk5p',
        'TransactionType': 'PaymentChannelCreate',
        'Amount': '"+amnt+"',
        'Destination': 'rD6CGd2uL9DZUVDNghMqAfr8doTzKbEtGA',
        'SettleDelay': 86400,
        'PublicKey': '023693F15967AE357D0327974AD46FE3C127113B1110D6044FD41E723689F81CC6',
        'DestinationTag': 20170428
    },
    'fee_mult_max': 1000
}]

        }";
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
Jitender
  • 330
  • 2
  • 11
  • 'Amount': '"+amnt+"', this field is giving error it is not correct format it shuold be 'Amount' : ' 100000 ', – Jitender Jun 06 '18 at 06:36
  • Map Json to object, then add the properties in the object declaration , Initialise the value, and serialise it back to json – Drag and Drop Jun 06 '18 at 06:37
  • What about something like @$"'Amount': '{amnt}'"? – Federico Navarrete Jun 06 '18 at 06:39
  • 'Amount' : ' 100000000 ' i need this if i am doing this it running successfully but i want to remove 6 zeros and after then 100 will be left and it should be dynamic. – Jitender Jun 06 '18 at 06:41
  • solution will be declaring an string externally but placing string variable in string json is giving error – Jitender Jun 06 '18 at 06:42
  • Please specify the error you're getting. Writing "is giving error" is never nearly as useful as including the full error (whether a compile-time error or an exception) in the question. – Jon Skeet Jun 06 '18 at 06:49

4 Answers4

8

The immediate problem is that you've got two string literals: a verbatim string literal at the start, and then a regular string literal after the string concatenation with amnt. To make it simpler to see, you've got:

string text = @"some text
                more text" + amnt + "more text
                more text";

That second string literal is a regular string literal, which means it can't go over multiple lines. That's why you're getting an error at the moment.

That's not the only problem you've got though:

  • The JSON you're producing at the moment is invalid anyway, as all of these single quotes should be double quotes. While several JSON parsers will allow single quotes, this does violate RFC 7159
  • Putting everything in string literals is a very brittle way of producing JSON. It's very easy to make a small typo and end up with invalid JSON.

There are several options here:

  • You could use a verbatim interpolated string literal, allowing you to write a single literal with {amnt} to include the value there. The disadvantage is that you'd need to double all the braces to indicate that you wanted actual braces
  • You could make the second string literal a verbatim string literal, by adding @ at the start of it
  • You could avoid doing all of this in strings to start with and use a JSON library to produce the JSON.

I'd definitely take the last option - I'd use Json.NET.

There are lots of ways of doing this in Json.NET. For example:

  • You could model the JSON object in regular classes, and serialize instances of those classes. If you need this JSON more than once, that's what I'd do. That would let you use idiomatic C# names for properties, using attributes to specify how those properties should be represented in JSON.
  • You could use LINQ to JSON to create JObject and JArray instances.
  • You could use an anonymous type.

Here's an example of the latter approach:

using System;
using Newtonsoft.Json;

class Test
{
    public static void Main()
    {
        string amount = "1000000";
        var obj = new
        {
            method = "submit",
            // Note: @ is required as params is a keyword
            @params = new[]
            {
                new
                {
                    secret = "snL7AcZbKsHm1H7VjeZg7gNS55Xkd",
                    tx_json = new
                    {
                        Account = "rHSqhmuevNJg9ZYpspYHNnQDxraozuCk5p",
                        TransactionType = "PaymentChannelCreate",
                        Amount = amount,
                        Destination = "rD6CGd2uL9DZUVDNghMqAfr8doTzKbEtGA",
                        SettleDelay = 86400,
                        PublicKey = "023693F15967AE357D0327974AD46FE3C127113B1110D6044FD41E723689F81CC6",
                        DestinationTag = 20170428
                    },
                    fee_mult_max = 1000
                }
            }
        };
        string json = JsonConvert.SerializeObject(obj, Formatting.Indented);
        Console.WriteLine(json);
    }
}

Output:

{
  "method": "submit",
  "params": [
    {
      "secret": "snL7AcZbKsHm1H7VjeZg7gNS55Xkd",
      "tx_json": {
        "Account": "rHSqhmuevNJg9ZYpspYHNnQDxraozuCk5p",
        "TransactionType": "PaymentChannelCreate",
        "Amount": "1000000",
        "Destination": "rD6CGd2uL9DZUVDNghMqAfr8doTzKbEtGA",
        "SettleDelay": 86400,
        "PublicKey": "023693F15967AE357D0327974AD46FE3C127113B1110D6044FD41E723689F81CC6",
        "DestinationTag": 20170428
      },
      "fee_mult_max": 1000
    }
  ]
}
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • ok... daisy i am just trying your method for replacing with my current method ...just give me time for that.. – Jitender Jun 06 '18 at 08:01
3

you need to put @ symbol twice once at the begining once after amnt+

string amnt = "100000000";
      string json = @"
    {
       'method': 'submit',
      'params': [{
       'secret': 'snL7AcZbKsHm1H7VjeZg7gNS55Xkd',
        'tx_json': {
    'Account': 'rHSqhmuevNJg9ZYpspYHNnQDxraozuCk5p',
    'TransactionType': 'PaymentChannelCreate',
    'Amount': '"+amnt+@"', //change here
    'Destination': 'rD6CGd2uL9DZUVDNghMqAfr8doTzKbEtGA',
    'SettleDelay': 86400,
    'PublicKey': '023693F15967AE357D0327974AD46FE3C127113B1110D6044FD41E723689F81CC6',
    'DestinationTag': 20170428
     },
'fee_mult_max': 1000
      }]

    }";

as mentioned here https://stackoverflow.com/a/556142/1322204 @ marks the string as a verbatim string literal - anything in the string that would normally be interpreted as an escape sequence is ignored. so adding that extra @ after the amnt+ tells that this is a multi-line string.

Sujit.Warrier
  • 2,815
  • 2
  • 28
  • 47
  • 2
    Note that you haven't actually *explained* why the OP needs to do this - and they're still left with invalid JSON, and pretty brittle code. I would *strongly* recommend using a JSON library for this instead of brittle string literals. – Jon Skeet Jun 06 '18 at 06:49
  • dude can you tell me if i want to mention destination tag without single quotes in this json and declaring another string then what to do? – Jitender Jun 06 '18 at 06:55
  • @Jitender didnt get you – Sujit.Warrier Jun 06 '18 at 06:57
  • 'DestinationTag': 20170428 is not in single quotes it is like intiger value in this json and i want to give this 20170428 in dynamic for that i have to declare it in string variable externally like you solved my previous problem but this is not in single quotes – Jitender Jun 06 '18 at 07:01
  • ok 'DestinationTag':"+ intDestTag+@", the single quotes dont matter – Sujit.Warrier Jun 06 '18 at 07:02
  • it treats everything as string. it doesnt care if the json has quotes or not – Sujit.Warrier Jun 06 '18 at 07:03
  • @Sujit.Warrier: Note that this is another example of why it's more maintainable not to do all of this through string literals. Using JSON.NET (whether using an anonymous type as per my answer or not) you can make it a string value or an integer value trivially, however you want. The type of the value you use will be reflected in the JSON automatically. – Jon Skeet Jun 06 '18 at 07:04
  • @DaisyShipton using JObject and JArray is much better. true – Sujit.Warrier Jun 06 '18 at 07:05
  • @Jitender: Can I check that you are aware that you're still creating invalid JSON this way? The string you're producing may work for whatever's consuming it *at the moment* but if it ever changes to be stricter about the JSON it consumes, you'll need to change everywhere that you're producing JSON. That's a risk you can decide to take of course, but you should do so *knowing* that you're taking it. – Jon Skeet Jun 06 '18 at 07:08
  • Daisy Shipton....but this json is working fine and successfully giving result now. – Jitender Jun 06 '18 at 07:17
  • @Jitender: That doesn't mean it's valid JSON. It just means that whatever is parsing it is doing so in a lenient manner. It doesn't conform to the JSON RFC. If you're happy to knowingly produce invalid JSON (and do so in a way that's brittle and hard to maintain, IMO) then that's your choice - but I want to make sure that you're doing so *knowingly* rather than being unaware that it's invalid. – Jon Skeet Jun 06 '18 at 07:35
  • ok so what will be the right method according to you Daisy..i am keen to know that. – Jitender Jun 06 '18 at 07:40
  • @Jitender: That's why I've provided an answer with a complete example using Json.NET to create the JSON in a more robust way :) – Jon Skeet Jun 06 '18 at 07:41
0

I think you want to do something like this:

string amnt = "100000000";
string json = $@"
{{
    'method': 'submit',
    'params': [{{
        'secret': 'snL7AcZbKsHm1H7VjeZg7gNS55Xkd',
        'tx_json': {{
            'Account': 'rHSqhmuevNJg9ZYpspYHNnQDxraozuCk5p',
            'TransactionType': 'PaymentChannelCreate',
            'Amount': '{amnt}',
            'Destination': 'rD6CGd2uL9DZUVDNghMqAfr8doTzKbEtGA',
            'SettleDelay': 86400,
            'PublicKey': '023693F15967AE357D0327974AD46FE3C127113B1110D6044FD41E723689F81CC6',
            'DestinationTag': 20170428
        }},
        'fee_mult_max': 1000
    }}]
}}";

The $ symbol is for interpolating strings, you can read more here:

https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/tokens/interpolated

Also, if you have objects you could consider to use JSON.NET

https://bridge.net/jsonnet

Federico Navarrete
  • 3,069
  • 5
  • 41
  • 76
0

Best answer so far is from Sujit.Warrier

However the old replace works good as well

    string amnt = "100000000";
                string json = @"
           {
    'method': 'submit',
    'params': [{
        'secret': 'snL7AcZbKsHm1H7VjeZg7gNS55Xkd',
        'tx_json': {
            'Account': 'rHSqhmuevNJg9ZYpspYHNnQDxraozuCk5p',
            'TransactionType': 'PaymentChannelCreate',
            'Amount': '{amnt}',
                'Destination': 'rD6CGd2uL9DZUVDNghMqAfr8doTzKbEtGA',
                'SettleDelay': 86400,
                'PublicKey': '023693F15967AE357D0327974AD46FE3C127113B1110D6044FD41E723689F81CC6',
                'DestinationTag': 20170428
            },
            'fee_mult_max': 1000
        }]

    }";

MessageBox.Show( json.Replace("{amnt}", amnt));
Pon Saravanan
  • 525
  • 5
  • 12
  • I don't think using string literals for this is the best answer at all. Both this answer and Sujit.Warrier's still leave a brittle, easy-to-mess-up string literal that gives invalid JSON. There's no need for that - there are plenty of alternatives that create valid JSON in a more readable and maintainable manner. – Jon Skeet Jun 06 '18 at 06:53
  • Best is subjective. Depends on the needs string literals can be still used. – Pon Saravanan Jun 06 '18 at 06:57
  • There's some subjectivity, but the fact that a) this still produces invalid JSON and b) any changes would require significant care to make sure the structure is still valid (making sure opening and closing braces go in the right place etc) suggest to me that this isn't a good idea. If you're going to argue it's subjective, then I'd say there's little point in stating it at the start of your answer (especially in a way that *suggests* it's objective rather than a matter of opinion). – Jon Skeet Jun 06 '18 at 07:03
  • It is based on the given question. He asked for single quotes and want to have it in single quotes. so based on his needs that is the best answer for his needs Please refer back to the question ' I want to declare it in json amount in single quotes' – Pon Saravanan Jun 06 '18 at 07:05
  • Indeed, it answers the question - but leaves the OP with invalid JSON without indicating that at all. It's like providing an answer that uses string concatenation for values in a SQL statement instead of recommending parameterized SQL. I view it as a "duty of care" to highlight other significant problems with the OP's code... and I'd view an answer that produces valid JSON as better than an answer that produces invalid JSON unless the OP has indicated that they're aware that the JSON is invalid and they have some special reason for *desiring* invalid JSON. – Jon Skeet Jun 06 '18 at 07:07
  • Thats why I am saying thats based on your assumption and subjective. – Pon Saravanan Jun 06 '18 at 07:08
  • Okay, if you think valid JSON is only subjectively better than invalid JSON, I think we'll have to agree to disagree. – Jon Skeet Jun 06 '18 at 07:09
  • Look which solution he has prefered in the answers. There are various reasons one might choose no matter that is good or not. I agree that your solution is great And I would choose over the others. But based on his needs the one directly address the problem with little efforts is what I have mentioned. – Pon Saravanan Jun 06 '18 at 07:12