1

I have to send a data by post in JSON format. I have my nsdictionary with keys and values.

NSDictionary *params_country=[NSDictionary dictionaryWithObjectsAndKeys:
    @"1111",@"@id",
    nil];

NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:
    @"dummy3", @"@name",
    @"dummy3@example.com", @"@mail",
    @"password",@"@password", params_country,@"country",
    nil];

When i am doing a log

DLog(@"params %@",[params description]);

I am getting the following

params {
    "@mail" = "dummy3@example.com";
    "@name" = dummy3;
    "@password" = password; 
}

The problem is that i have to sent the JSON in the order that i have listed in the above initialisation of my nsdictionary but the keys are being sorted somehow.

Any solution?

EDIT

Sorry i am sending a nsdictionary also in the params. If i remove the country then its fine.

Alladinian
  • 34,483
  • 6
  • 89
  • 91
veereev
  • 2,650
  • 4
  • 27
  • 40

2 Answers2

1

Dictionaries are an unordered collection type. If you need to maintain a certain order, then you should use an ordered collection type like NSArray. But for this, your web service shouldn't care about the order, since it should be looking up the values by the keys provided.

Aaron Brager
  • 65,323
  • 19
  • 161
  • 287
  • Hello there thanks for your reply, but in my case yes the webservice is taking care of the order. So i should send the data in ordered way. – veereev Dec 09 '13 at 06:56
  • 5
    This is a violation of the JSON spec, which says "An object is an unordered collection of zero or more name/value pairs, where a name is a string and a value is a string, number, boolean, null, object, or array." What you are working with is therefore not JSON. If you want this to work you'll need to build your own NSData object, or you could just fix your web service. – Aaron Brager Dec 09 '13 at 06:59
1

As per some of the comments, this requirement does not match a valid JSON object as the official JSON Specification states:

An object is an unordered set of name/value pairs. An object begins with { (left brace) and ends with } (right brace). Each name is followed by : (colon) and the name/value pairs are separated by , (comma).

Unfortunately we don't live in a perfect world with perfect web services and there are often certain things that are out of our control.

I wrote a subclass of NSMutableDictionary after reading up on the internet that will order the dictionary based on the order you call setValue:forKey:.

I put the class into a gist you can download from here: https://gist.github.com/liamnichols/7869468 or you can just copy it from below:

LNOrderedMutableDictionary.h

@interface LNOrderedMutableDictionary : NSMutableDictionary

///If `anObject` is nil, it will not be added to the dictionary.
- (void)setNothingIfNil:(id)anObject forKey:(id)aKey;

@end

LNOrderedMutableDictionary.m

#import "LNOrderedMutableDictionary.h"

@interface LNOrderedMutableDictionary ()

@property (nonatomic, strong) NSMutableDictionary *dictionary;
@property (nonatomic, strong) NSMutableOrderedSet *array;

@end

@implementation LNOrderedMutableDictionary

- (id)initWithCapacity:(NSUInteger)capacity
{
    self = [super init];
    if (self != nil)
    {
        self.dictionary = [[NSMutableDictionary alloc] initWithCapacity:capacity];
        self.array = [[NSMutableOrderedSet alloc] initWithCapacity:capacity];
    }
    return self;
}

- (id)init
{
    self = [self initWithCapacity:0];
    if (self)
    {

    }
    return self;
}

- (void)setObject:(id)anObject forKey:(id)aKey
{
    [self.array removeObject:aKey];
    [self.array addObject:aKey];
    [self.dictionary setObject:anObject forKey:aKey];
}

- (void)setNothingIfNil:(id)anObject forKey:(id)aKey
{
    if (anObject != nil)
        [self setObject:anObject forKey:aKey];
}

- (void)removeObjectForKey:(id)aKey
{
    [self.dictionary removeObjectForKey:aKey];
    [self.array removeObject:aKey];
}

- (NSUInteger)count
{
    return [self.dictionary count];
}

- (id)objectForKey:(id)aKey
{
    return [self.dictionary objectForKey:aKey];
}

- (NSEnumerator *)keyEnumerator
{
    return [self.array objectEnumerator];
}

@end

If possible, your web service shouldn't have to rely on the JSON objects to be formatted in a specific order but if there is nothing you can do to change this then the above solution is what you are looking for.

Source: cocoawithlove

liamnichols
  • 12,419
  • 2
  • 43
  • 62