Search code examples
objective-cjsonnsattributedstringnsjsonserialization

How to reconstruct NSAttributedString from JSON data


I have this NSAttributedString object that I have managed to write in a file like this:

{
  "string" : "Hello World",
  "runs" : [
    {
      "range" : [0,3],
      "attributes" : {
        "font" : {
          "name" : "Arial",
          "size" : 12
        }
      }
    },
    {
      "range" : [3,6],
      "attributes" : {
        "font" : {
          "name" : "Arial",
          "size" : 12
        },
        "color" : [255,0,0]
      }
    },
    {
      "range" : [9,2],
      "attributes" : {
        "font" : {
          "name" : "Arial",
          "size" : 12
        }
      }
    }
  ]
}

Now I have to read the data back and reconstruct the NSAttributedString
any ideas?


Solution

  • Deserialize your JSON string to get a dictionary with values. Then parse out the bits as you need them.

    First parse out the string:

    NSString *myString = [dictionaryFromJson objectForKey:@"string"];
    NSMutableAttributedString *myAttributedString = [[NSMutableAttributedString alloc] initWithString:myString];
    

    Then parse out the array:

    NSArray *attributes = [dictionaryFromJson objectForKey:@"runs"];
    

    Then traverse the array and for each dictionary in it, create the attributes as needed:

    for(NSDictionary *dict in attributes)
    {
        NSArray *rangeArray = [dict objectForKey:@"range"];
        NSRange range = NSMakeRange([(NSNumber*)[rangeArray objectAtIndex:0] intValue], [(NSNumber*)[rangeArray objectAtIndex:0] intValue]); //you may need to make sure here your types in array match up and of course that you are in bounds of array
    
        NSDictionary *attributesDictionary = [dict objectForKey:@"attributes"];
    
        //I'll do the font as example
        NSDictionary *fontDictionary = [attributesDictionary objectForKey:@"font"];
        if(fontDictionary)
        {
            NSString *fontName = [fontDictionary objectForKey:@"name"];
            float fontSize = [[fontDictionary objectForKey:@"size"] floatValue];
            UIFont *myFont = [UIFont fontWithName:fontName size:fontSize];
    
            if(myFont)
            {
                 [myAttributedString addAttribute:NSFontAttributeName value:myFont range:range];
            }
        }
    }
    

    Then just carry on with the rest of the values, manipulating data based on whether they come from dictionaries or arrays.

    You will also need to do some validation, null-checks etc., so this code is by no means complete.