This commit is contained in:
Hugo Melder 2025-04-18 09:24:36 +00:00 committed by GitHub
commit 2c8b44f334
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 59 additions and 10 deletions

View file

@ -50,7 +50,13 @@ enum
* If this is not set, then the writer will not generate any superfluous
* whitespace, producing space-efficient but not very human-friendly JSON.
*/
NSJSONWritingPrettyPrinted = (1UL << 0)
NSJSONWritingPrettyPrinted = (1UL << 0),
#if OS_API_VERSION(MAC_OS_X_VERSION_10_13, GS_API_LATEST)
/**
* When writing JSON, sort keys in lexicographic order.
*/
NSJSONWritingSortedKeys = (1UL << 1)
#endif
};
/**
* A bitmask containing flags from the NSJSONWriting* set, specifying options

View file

@ -860,7 +860,7 @@ writeNewline(NSMutableString *output, NSInteger tabs)
}
static BOOL
writeObject(id obj, NSMutableString *output, NSInteger tabs)
writeObject(id obj, NSMutableString *output, NSInteger tabs, NSJSONWritingOptions opt)
{
if ([obj isKindOfClass: NSArrayClass])
{
@ -874,7 +874,7 @@ writeObject(id obj, NSMutableString *output, NSInteger tabs)
writeComma = YES;
writeNewline(output, tabs);
writeTabs(output, tabs);
writeObject(o, output, tabs + 1);
writeObject(o, output, tabs + 1, opt);
END_FOR_IN(obj)
writeNewline(output, tabs);
writeTabs(output, tabs);
@ -883,8 +883,15 @@ writeObject(id obj, NSMutableString *output, NSInteger tabs)
else if ([obj isKindOfClass: NSDictionaryClass])
{
BOOL writeComma = NO;
NSArray *keys = [obj allKeys];
[output appendString: @"{"];
FOR_IN(id, o, obj)
if ((opt & NSJSONWritingSortedKeys) == NSJSONWritingSortedKeys)
{
keys = [keys sortedArrayUsingSelector: @selector(compare:)];
}
FOR_IN(id, o, keys)
// Keys in dictionaries must be strings
if (![o isKindOfClass: NSStringClass]) { return NO; }
if (writeComma)
@ -894,10 +901,11 @@ writeObject(id obj, NSMutableString *output, NSInteger tabs)
writeComma = YES;
writeNewline(output, tabs);
writeTabs(output, tabs);
writeObject(o, output, tabs + 1);
[output appendString: @": "];
writeObject([obj objectForKey: o], output, tabs + 1);
END_FOR_IN(obj)
writeObject(o, output, tabs + 1, opt);
[output appendString: @":"];
writeObject([obj objectForKey: o], output, tabs + 1, opt);
END_FOR_IN(keys)
writeNewline(output, tabs);
writeTabs(output, tabs);
[output appendString: @"}"];
@ -1062,7 +1070,7 @@ writeObject(id obj, NSMutableString *output, NSInteger tabs)
tabs = ((opt & NSJSONWritingPrettyPrinted) == NSJSONWritingPrettyPrinted) ?
0 : NSIntegerMin;
if (writeObject(obj, str, tabs))
if (writeObject(obj, str, tabs, opt))
{
data = [str dataUsingEncoding: NSUTF8StringEncoding];
if (NULL != error)
@ -1089,7 +1097,7 @@ writeObject(id obj, NSMutableString *output, NSInteger tabs)
+ (BOOL) isValidJSONObject: (id)obj
{
return writeObject(obj, nil, NSIntegerMin);
return writeObject(obj, nil, NSIntegerMin, 0);
}
+ (id) JSONObjectWithData: (NSData *)data

View file

@ -0,0 +1,35 @@
#import <Foundation/Foundation.h>
#import "ObjectTesting.h"
void testLexicographicalOrder() {
NSArray *objects =
[NSArray arrayWithObjects:@"a", @"b", @"c", @"d", @"e", nil];
NSArray *keys = [NSArray
arrayWithObjects:@"c_ab", @"a_ab", @"d_ab", @"f_cb", @"f_ab", nil];
NSDictionary *dict = [NSDictionary dictionaryWithObjects:objects
forKeys:keys];
NSError *error = nil;
NSData *actualData =
[NSJSONSerialization dataWithJSONObject:dict
options:NSJSONWritingSortedKeys
error:&error];
PASS_EQUAL(error, nil, "no error occurred during serialisation");
NSString *actual = [[NSString alloc] initWithData:actualData
encoding:NSUTF8StringEncoding];
NSString *expected = @"{\"a_ab\":\"b\",\"c_ab\":\"a\",\"d_ab\":\"c\",\"f_"
"ab\":\"e\",\"f_cb\":\"d\"}";
PASS_EQUAL(actual, expected, "JSON is correctly sorted");
NSLog(@"%@", actual);
}
int main(void) {
NSAutoreleasePool *arp = [NSAutoreleasePool new];
testLexicographicalOrder();
[arp release];
return 0;
}