Forum Xamarin.Forms
We are excited to announce that the Xamarin Forums are moving to the new Microsoft Q&A experience. Q&A is the home for technical questions and answers at across all products at Microsoft now including Xamarin!

We encourage you to head over to Microsoft Q&A for .NET for posting new questions and get involved today.

Xamarin Forms IOS - NSData from a json string

RicardoPORRicardoPOR Member ✭✭
edited June 2019 in Xamarin.Forms

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?

Best Answers

  • RicardoPORRicardoPOR Member ✭✭
    Accepted Answer

    I found a solution.. quite simple:

    NSData jsonData = NSData.FromString(jsonSerialized, NSStringEncoding.UTF8);
    

Answers

  • RicardoPORRicardoPOR Member ✭✭
    Accepted Answer

    I found a solution.. quite simple:

    NSData jsonData = NSData.FromString(jsonSerialized, NSStringEncoding.UTF8);
    
  • RicardoPORRicardoPOR Member ✭✭

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

  • ColeXColeX Member, Xamarin Team Xamurai

    @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.

  • RicardoPORRicardoPOR Member ✭✭

    @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

  • JoannaGJoannaG Member ✭✭

    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/us_states.geojson
                StreamReader inputStream = new StreamReader(filename);
                string Us_country_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(Us_country, Us_country));
    
                        //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.

  • JoannaGJoannaG Member ✭✭

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

  • RicardoPORRicardoPOR Member ✭✭

    @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

Sign In or Register to comment.