-138

I'm using a WEB API to receive a request from a Client application to save Contact Information, and I need to send an Error Message only if the data has an error; otherwise nothing TODO

Earlier I Used a Dictionary<string, string>

For Example:

Dictionary<string, string> error = new Dictionary<string, string>
{
    {"SaveContactMethod_1", "FirstName Invalid"},
    {"SaveContactMethod_2", "LastName Invalid"},
    {"SaveContactMethod_3", "MiddleName Invalid"},
}

the respective JSON Object is

{
    "error" : {
        "SaveContactMethod_1":"FirstName Invalid",
        "SaveContactMethod_2":"LastName Invalid",
        "SaveContactMethod_3":"MiddleName Invalid"
    }
}

But I need an UNIQUE Key (i.e., Duplicate Key), So I changed the Dictionary<string, string> to List<KeyValuePair<string, string>>

List<KeyValuePair<string, string>> error = new List<KeyValuePair<string, string>>
{
    new KeyValuePair<string, string>("SaveContactMethod", "FirstName Invalid"),
    new KeyValuePair<string, string>("SaveContactMethod", "LastName Invalid"),
    new KeyValuePair<string, string>("SaveContactMethod", "MiddleName Invalid"),
}

the respective JSON Object is

{
    "error" : [
        { "key":"SaveContactMethod", "value":"FirstName Invalid" },
        { "key":"SaveContactMethod", "value":"LastName Invalid" },
        { "key":"SaveContactMethod", "value":"MiddleName Invalid" }
    ]
}

My Requirement: I need to add a Duplicate Key and I need the Json Output like a Dictionary.

Expected Output: JSON

{
    "error" : {
        "SaveContactMethod":"FirstName Invalid",
        "SaveContactMethod":"LastName Invalid",
        "SaveContactMethod":"MiddleName Invalid"
    }
}
davidsbro
  • 2,761
  • 4
  • 23
  • 33
B.Balamanigandan
  • 4,713
  • 11
  • 68
  • 130
  • 1
    Dictionary> may work. One key to a list value. this wont look like your expected tho – Luminous_Dev Feb 22 '17 at 06:56
  • @Luminous_Dev - But it won't give the expected JSON. – B.Balamanigandan Feb 22 '17 at 06:56
  • 5
    Would multiple `"SaveContactMethod":"Foo"` be even valid JSON, if that is what you want? – Christian Gollhardt Feb 22 '17 at 06:58
  • @ChristianGollhardt - It's a valid JSON but it produce Warning **"Warning:Duplicate key, names should be unique."** – B.Balamanigandan Feb 22 '17 at 07:00
  • 1
    @ChristianGollhardt I was thinking the same thing. That's not valid JSON because you have duplicate property names. – Eric Sondergard Feb 22 '17 at 07:00
  • @B.Balamanigandan So, it's not valid JSON then. – Eric Sondergard Feb 22 '17 at 07:00
  • @EricSondergard - Warning is different than Error. The said format is a Valid JSON – B.Balamanigandan Feb 22 '17 at 07:02
  • does not work key value would never have duplicate key, if you can have duplicate key, use of keyvaluepair is meaning less – Luminous_Dev Feb 22 '17 at 07:02
  • @Luminous_Dev - Yeah, I need a better solution for this. Anyone please assist me. – B.Balamanigandan Feb 22 '17 at 07:03
  • 1
    `Dictionary>` would be what you need as initially mentioned – Luminous_Dev Feb 22 '17 at 07:03
  • 24
    Maybe you need to talk to your client and explain to them this is a stupid requirement likely to introduce all sorts of problems down the road? – Pekka Feb 22 '17 at 08:45
  • 49
    Yes, technically that is valid JSON, however, it's *meaning* according to the spec is that preceding duplicate keys are ignored. Hence the warnings in your online tools. The JSON is invalid if you care about the integrity of your data. Since you do care about the integrity, you can no longer call it JSON. It's now your own custom format that happens to resemble JSON – Rob Feb 22 '17 at 11:00
  • 54
    And in a few days, we'll see a question from another developer from this company: *"How do I parse JSON with duplicate keys? I need all the values, but my library only returns the last one."* Oh, well... – Heinzi Feb 23 '17 at 07:30
  • 1
    @Heinzi - Here the question is returning JSON with duplicate keys not for parsing. First try to understand the requirement of the question then reply. – B.Balamanigandan Feb 23 '17 at 07:52
  • 20
    @B.Balamanigandan: I'm talking about the poor guy who will have to parse the output you are creating, not about you. :-) – Heinzi Feb 23 '17 at 08:32
  • 33
    Any time you find yourself saying "I need a duplicate key", I think it's time to rethink your design. – JLRishe Feb 23 '17 at 11:49
  • 4
    why does this question have -113 votes? – d51 Aug 18 '20 at 09:56
  • 3
    @dan51 2 reasons. The first one is that "Duplicate Key" is an oxymoron and possibly the most stupid thing most of us ever heard a developer say. Keys, by definition, are unique. The 2nd reason is that the OP invited everyone (intentionally? not sure) to come and downvote it by posting a comment here: https://meta.stackexchange.com/questions/11017/what-are-the-most-upvoted-downvoted-questions-and-answers-on-the-sites – rmcsharry Oct 25 '20 at 14:05

2 Answers2

114

You have a classic "XY" problem. You have asked "How do I do X", but you really need to do Y and you think that X is the only way to get to Y -- but X is either impossible or very hard. By changing your requirements a little, you can get to Y a different way, but you haven't seen that yet since you're stuck on X.

Here's your X: the JSON format that you want to get:

{
    "error" : {
        "SaveContactMethod":"FirstName Invalid",
        "SaveContactMethod":"LastName Invalid",
        "SaveContactMethod":"MiddleName Invalid"
    }
}

This will, as others have said, throw away all the error messages except for one when you load it into your C# code.

However, there's a very simple way to get all the error messages. You simply need to change the JSON you're expecting to look something like this instead:

{
    "error" : {
        "SaveContactMethod": [
            "FirstName Invalid",
            "LastName Invalid",
            "MiddleName Invalid"
        ]
    }
}

If you only had a single error message, you should still use a list:

{
    "error" : {
        "SaveContactMethod": [
            "FirstName Invalid"
        ]
    }
}

That way when you load the JSON into your C# code, it will always have the same type, Dictionary<string,List<string>>, whether there was one error or many.

That's the Y in your XY problem. Instead of beating your head against the wall of "I want to have duplicate keys in JSON", find a way around the wall: have a single key with a list of values. And now you can do what you really needed, which is to get all the error messages from your form with just a single key name for every single error message.

rmunn
  • 34,942
  • 10
  • 74
  • 105
107

No, this is not possible.

This would be invalid* JSON:

{
    "error" : {
        "SaveContactMethod":"FirstName Invalid",
        "SaveContactMethod":"LastName Invalid",
        "SaveContactMethod":"MiddleName Invalid"
    }
}

You can check this here:

Warning:Duplicate key, names should be unique.[Code 23, Structure 9]
Warning:Duplicate key, names should be unique.[Code 23, Structure 13]

*Depending on what you call valid

If you realy want to go this route, according to RFC 4627, you could use the StringBuilder class.


Since you don't seem to understand, what Depending on what you call valid means.

ECMA-262:

In the case where there are duplicate name Strings within an object, lexically preceding values for the same key shall be overwritten.

That means: If you get three SaveContactMethod's, you only want "MiddleName Invalid" in ECMA Script (JS). With c# serialization, this would not even be possible. You need to write your own JsonSerializer for it.

Community
  • 1
  • 1
Christian Gollhardt
  • 16,510
  • 17
  • 74
  • 111
  • 16
    Just to expand on this, it's important to remember that JSON represents an *object*. You couldn't create an object with duplicate property names in any other OO concept that I know of. Sure it will compile without errors (albeit with warnings), but it won't actually be usable. – Eric Sondergard Feb 22 '17 at 07:03
  • Sure, sure. It's not strictly invalid. But I would be shocked if you can find a JSON serializer that will do what you're asking. – Eric Sondergard Feb 22 '17 at 07:11
  • 1
    I assume what VALID here meaning only the syntax of json string is valid saying that opening and closing is done properly....etc – Luminous_Dev Feb 22 '17 at 07:13
  • 4
    @Luminous_Dev Really what I'm most curious about here is how in the world the API makes something usable out of JSON with duplicate keys... – Eric Sondergard Feb 22 '17 at 07:14
  • I think the expected output shouldn't be expected and needs to be designed better. A single key with an array of messages? – CRice Feb 22 '17 at 07:17
  • 23
    Your requirement makes no sence, as long as you need to work with your JSON programmaticaly @B.Balamanigandan. You realy should use a simple errorMessage field, wich is an array of error messages. That's the [xy](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) problem. – Christian Gollhardt Feb 22 '17 at 07:21
  • @ChristianGollhardt - How to achieve the said JSON using C#, we can discuss the issues of JSON later. Prior to that we can discuss how to construct using C#. – B.Balamanigandan Feb 22 '17 at 07:24
  • @ChristianGollhardt - Could you please share your comment in Answer block. – B.Balamanigandan Feb 22 '17 at 07:26
  • @ChristianGollhardt - I know StringBuilder, but I don't know how to achieve the JSON using this builtin function. Could you please share your code. – B.Balamanigandan Feb 22 '17 at 07:37
  • 1
    Use `foreach` and `StringBuilder::AppendLine()` @B.Balamanigandan. Seriously, no serialization. Only manual string concat would be the way. – Christian Gollhardt Feb 22 '17 at 07:40
  • @ChristianGollhardt - If you did like this, the WEB API return the object as a String `"SaveContactMethod:FirstName Invalid"` instead of Key:Value (i.e., `"SaveContactMethod":"FirstName Invalid"`) – B.Balamanigandan Feb 22 '17 at 07:42
  • Is there a reason why you are only wanting that JSONformat and not looking for ANOTHER json format? because serializing that would never ever work. – Luminous_Dev Feb 22 '17 at 07:49
  • @ChristianGollhardt - Don't escape smartly. The answer you posted in the answer block is not an answer what you said in the last comment. Try to give the answer using String Builder. – B.Balamanigandan Feb 22 '17 at 07:50
  • @Luminous_Dev - The client requirement is as like what I posted. That's why I'm trying to get the solution. – B.Balamanigandan Feb 22 '17 at 07:51
  • 41
    @B.Balamanigandan, the requirement is not possible. Read the documentation if you need help with StringBuilder. But that is not the way you should do it, and I will not write it for you. This would be way to broad. Change the requirement by talking to the person who give you the requirement. Communicate to this person why it is a bad requirement. Reference to your question here. But that's the end of my part of this discussion. Sorry about that. I also have my projects that needs to be done. Maybe someone else writes a solution that fits your needs. Feel free to downvote my answer. – Christian Gollhardt Feb 22 '17 at 07:57
  • Comments are not for extended discussion; this conversation has been [moved to chat](http://chat.stackoverflow.com/rooms/136330/discussion-on-answer-by-christian-gollhardt-return-json-object-of-listkeyvaluep). – Bhargav Rao Feb 22 '17 at 09:45