locked
Xamarin Forms IOS - NSData from a json string RRS feed

  • Question

  • User382171 posted

    I'm trying to get an NSData from a json string, to use it later to create an MGLShape (From Mapbox SDK) like this:

    MGLShape.ShapeWithData(jsonData, 4, out error); //jsonData is the NSData, 4 is the nuint for the type of encoding and ou error is a plain NSError.
    

    But i'm not able to serialize the json string into NSData using NSJsonSerialization, the json string is corrected and validated before, (but when i use an NSString from the string, it adds an extra pair of brackets "{ //json }", which i can remove before trying the NSJsonSerialization, here is how i'm trying to achive my goal:

    string jsonSerialized = JsonConvert.SerializeObject(fc);//Valid Json
    NSString json = new NSString(jsonSerialized);//Adds the extra pair of brackets
    NSData jsonData = NSJsonSerialization.Serialize(json, NSJsonWritingOptions.SortedKeys, out error);
    

    But it gives me the following error:

    Foundation.MonoTouchException: Objective-C exception thrown.  Name: NSInvalidArgumentException Reason: *** +[NSJSONSerialization dataWithJSONObject:options:error:]: Invalid top-level type in JSON write
    

    This error happens with, or without the extra pair of brackets (removed the first and last chars from the NSString), here is a shortned version of my json: (i used https://jsonformatter.curiousconcept.com/ to test the json)

    {"type":"FeatureCollection","crs":null,"features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-9.000000,38.000000]},"properties":{"id":1,"icon":"MyIcon.png"}}]}
    

    What am i doing wrong here? how can i parse an json string into an NSData?

    Friday, June 7, 2019 11:11 AM

Answers

  • User382171 posted

    I found a solution.. quite simple:

    NSData jsonData = NSData.FromString(jsonSerialized, NSStringEncoding.UTF8);
    
    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Friday, June 7, 2019 2:16 PM
  • User369978 posted

    NSData Serialize(NSObject obj, NSJsonWritingOptions opt, out NSError error);

    obj here should be NSDictionary not NSString,check https://stackoverflow.com/a/30618924/8187800.

    I tried the following code , it works fine .

    NSDictionary json = NSDictionary.FromObjectAndKey(new NSString("a") , new NSString("a"));         
       NSData jsonData = NSJsonSerialization.Serialize(json, NSJsonWritingOptions.SortedKeys, out error);
    

    So you major problem is how to convert json string to NSDictionary.

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Friday, June 7, 2019 2:27 PM

All replies

  • User382171 posted

    I found a solution.. quite simple:

    NSData jsonData = NSData.FromString(jsonSerialized, NSStringEncoding.UTF8);
    
    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Friday, June 7, 2019 2:16 PM
  • User369978 posted

    NSData Serialize(NSObject obj, NSJsonWritingOptions opt, out NSError error);

    obj here should be NSDictionary not NSString,check https://stackoverflow.com/a/30618924/8187800.

    I tried the following code , it works fine .

    NSDictionary json = NSDictionary.FromObjectAndKey(new NSString("a") , new NSString("a"));         
       NSData jsonData = NSJsonSerialization.Serialize(json, NSJsonWritingOptions.SortedKeys, out error);
    

    So you major problem is how to convert json string to NSDictionary.

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Friday, June 7, 2019 2:27 PM
  • User382171 posted

    @ColeX it worked too! but i found my solution to be more simple

    Friday, June 7, 2019 2:53 PM
  • User369978 posted

    @RicardoPOR said: @ColeX it worked too! but i found my solution to be more simple

    Of course ,your solution is the direct method from NSString to NSData.

    Friday, June 7, 2019 2:56 PM
  • User382171 posted

    @ColeX said:

    @RicardoPOR said: @ColeX it worked too! but i found my solution to be more simple

    Of course ,your solution is the direct method from NSString to NSData.

    i was overcomplicating things up, thank you anyway for your time

    Friday, June 7, 2019 2:59 PM
  • User386272 posted

    Hi @colex,

    Am using naxam mapbox and struggling to load coordinates from json in ios . Here, my code tried in ios xamarin. ``` var bundlePath = NSBundle.MainBundle.BundlePath; var filename = Path.Combine(bundlePath,"StateBoundaries.json");//valid https://docs.mapbox.com/mapbox-gl-js/assets/usstates.geojson StreamReader inputStream = new StreamReader(filename); string Uscountry_jsonSerialized = inputStream.ReadToEnd(); NSError err;

            NSData jsonData = NSData.FromString(Us_country_jsonSerialized, NSStringEncoding.UTF8);
            var source = new MGLShapeSource("identifier",MGLShape.ShapeWithData(jsonData, 4,out err ),null);
            MapView.Style?.AddSource(source);
    
            var layer = new MGLFillStyleLayer(identifier: "layerIdentifier", source);
            layer.FillColor = NSExpression.FromConstant(UIColor.Yellow);
    

    I completed in android. //Added full country points. loadedMapStyle.AddSource(new GeoJsonSource(Uscountry, Uscountry));

                    //Filled each state with color
                    FillLayer countryPolygonFillLayer = new FillLayer(Us_country, Us_country);
                    countryPolygonFillLayer.SetProperties(
                    PropertyFactory.FillColor(Color.ParseColor("#D1F2EB55")));
                    loadedMapStyle.AddLayer(countryPolygonFillLayer);
    

    ``` My requirement is to fill color to full US region. But in ios alone my failing some how. Can you please find and let me know what am doing wrong.

    Thursday, July 30, 2020 6:09 AM
  • User386272 posted

    Hi @ColeX /@Ricardo, How do i can calculate nunit value given for MGLShape date

    Thursday, July 30, 2020 7:00 AM
  • User382171 posted

    @JoannaG said: Hi @ColeX /@Ricardo, How do i can calculate nunit value given for MGLShape date

    Hi @JoannaG, this is what i think you are looking for:

    first i created this classes with the geojson property names, that will make it easier to serialize to the geojson source:

    public class MapBoxFeatureCollection
    {
        public string type { get; set; }
        public Crs crs { get; set; }
        public List<MapFeaturePoint> features { get; set; }
    
        public class Properties
        {
            public string name { get; set; }
        }
    
        public class Crs
        {
            public string type { get; set; }
            public Properties properties { get; set; }
        }
    }
    

    public class MapFeaturePoint
    {
        public string type { get; set; }
        public Geometry geometry { get; set; }
        public Properties properties { get; set; }
    }
    
    public class Geometry
    {
        public string type { get; set; }
        public List<double> coordinates { get; set; }
    
        public double Latitude => coordinates != null ? coordinates[1] : 0;
        public double Longitude => coordinates != null ? coordinates[0] : 0;
    }
    
    public class Properties
    {
        public int id { get; set; }
        public string icon { get; set; }
    //More Properties can be added here
    }
    

    then i created this function that returns the geojson, by serializing the list of MapFeaturePoint:

        public MGLShape GenerateFeatureCollection(List<MapFeaturePoint> Points)
        {
            //Create MGLShape From MapPoints
            MapBoxFeatureCollection fc = new MapBoxFeatureCollection() { features = Points, type = "FeatureCollection" };
            string jsonSerialized = JsonConvert.SerializeObject(fc);
    
            NSError error = null;
            NSData jsonData = NSData.FromString(jsonSerialized, NSStringEncoding.UTF8);
            var shape = MGLShape.ShapeWithData(jsonData, 4, out error);
            return shape;
        }
    

    then you just need to use the shape when creating the source (added the code for geojson source options also):

            #region GeoJsonOptions
            var keys = new[]
                {
                        MGLShapeSourceOptions.Clustered,//If the points can cluster
                        MGLShapeSourceOptions.ClusterRadius, //Radius for the points to cluster
                        MGLShapeSourceOptions.MaximumZoomLevelForClustering//Maximum map zoom for points to cluster
                    };
            var objects = new NSObject[]
            {
                        FromObject(new NSNumber(false)),
                        FromObject(new NSNumber(30f)),
                        FromObject(new NSNumber(11f))
            };
            var GeojsonSourceOptions = new NSDictionary<NSString, NSObject>(keys, objects);
            #endregion
    
            var source = new MGLShapeSource("geojson-source", featureCollection, GeojsonSourceOptions);
            mapView.Style.AddSource(source);
    

    And that's how i add the source for the layers

    Thursday, July 30, 2020 9:42 PM