Home > Blockchain >  I need to rearrange a JSON but I cant find a solution
I need to rearrange a JSON but I cant find a solution

Time:11-04

This is the JSON im receiving, already filtered. (its coming from the google places autocomplete API)

{
    "predictions": [
        {
            "description": "Frankfurt am Main, Deutschland",
            "place_id": "ChIJxZZwR28JvUcRAMawKVBDIgQ",
        },
        {
            "description": "Frankfurt (Oder), Deutschland",
            "place_id": "ChIJb_u1AiqYB0cRwDteW0YgIQQ",
        },
        {
            "description": "Frankfurt Hahn Flughafen (HHN), Lautzenhausen, Deutschland",
            "place_id": "ChIJX3W0JgQYvkcRWBxGlm6csj0",
        }
    ],
    "status": "OK"
}

And I need to get this JSON into this format:

{
   "success":true,
   "message":"OK",
   "data":[
      {
         "description":"Frankfurt Hahn Flughafen (HHN), Lautzenhausen, Deutschland",
         "id":"ChIJX3W0JgQYvkcRWBxGlm6csj0"
      },
      {
         "description":"Frankfurt Airport (FRA), Frankfurt am Main, Deutschland",
         "id":"ChIJeflCVHQLvUcRMfP4IU3YdIo"
      },
      {
         "description":"Frankfurt Marriott Hotel, Hamburger Allee, Frankfurt am Main, Deutschland",
         "id":"ChIJdag3xFsJvUcRZtfKqZkzBAM"
      }
   ]
}
I would be very g

So predictions is just renamed to "data", we change rename status to message, move it up and add a success if the http-request that happened earlier was a success or not. This does not seem so hard on the first catch, but I can't seem to find resources to transform or rearrange JSON in C#.

I would be very grateful for any tips or resources, so I can get unstuck on this probably not so difficult task. I should mention I'm fairly new to all of this.

Thank you all in advance!

CodePudding user response:

First create classes thats represent your jsons

public class Prediction
    {
        public string description { get; set; }
        public string place_id { get; set; }
    }

    public class InputJsonObj
    {
        public Prediction[] predictions { get; set; }
        public string status { get; set; }
    }


    public class Datum
    {
        public string description { get; set; }
        public string id { get; set; }
    }

    public class OutPutJsoObj
    {
        public bool success { get; set; }
        public string message { get; set; }
        public List<Datum> data { get; set; }
        public  OutPutJsoObj(){ 
         data = new List<Datum>();
        }
    }

Then mapped objects (manually or using any of mapping libraries like AutoMapper) and create final json.

using Newtonsoft.Json;
InputJsonObj inputObj = JsonConvert.DeserializeObject<InputJsonObj >(inputJson);
OutPutJsoObj outObj = new OutPutJsoObj ();

foreach(var p in inputObj)
{
 outObj.Data.Add(new Datum() { descriptions = p.descriptions , id= p.place_id }
}
string outJson =  = JsonConvert.SerializeObject(outObj);

CodePudding user response:

Just parse the origional json and move the data to the new json object

  var origJsonObj = JObject.Parse(json);

    var fixedJsonObj = new JObject {
    new JProperty("success",true),
    new JProperty("message",origJsonObj["status"]),
    new JProperty("data",origJsonObj["predictions"])
  };

it is not clear from your question what should be a success value, but I guess maybe you need this line too

if (fixedJsonObj["message"].ToString() != "OK") fixedJsonObj["success"] = false;

if you just need a fixed json

json = fixedJsonObj.ToString();

or you can create c# class (Data for example) and deserilize

Data result= fixedJsonObj.ToObject<Data>();

CodePudding user response:

I like the answer from @Serge but if you're looking for a strongly typed approach we can model the input and output structure as the same set of classes and the output structure is similar, with the same relationships but only different or additional names this try this:

  • The process used here is described in this post but effectively we create write-only properties that will receive the data during the deserialization process and will format it into the properties that are expected in the output.
public class ResponseWrapper
{
    [JsonProperty("success")]
    public bool Success { get;set; }
    
    [JsonProperty("message")]
    public string Message { get;set; }
    [Obsolete("This field should not be used anymore, please use Message instead")]
    public string Status 
    { 
        get { return null; }
        set 
        { 
            Message = value; 
            Success = value.Equals("OK", StringComparison.OrdinalIgnoreCase);
        }
    }
    
    [JsonProperty("data")]
    public Prediction[] Data { get;set; }
    [Obsolete("This field should not be used anymore, please use Data instead")]
    public Prediction[] Predictions 
    { 
        get { return null; }
        set { Data = value; }
    }
}
public class Prediction
{
    public string description { get; set; }
    public string place_id { get; set; }
}

Then you can deserialize and re-serialize with this code:

using Newtonsoft.Json;
...
var input = JsonConvert.DeserializeObject<ResponseWrapper>(input);
var output = JsonConvert.SerializeObject(objs, new JsonSerializerSettings 
             { 
                 Formatting = Newtonsoft.Json.Formatting.Indented, 
                 NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore 
             });

This is a fiddle you can test with: https://dotnetfiddle.net/DsI5Yc And the output:

{
  "success": true,
  "message": "OK",
  "data": [
    {
      "description": "Frankfurt am Main, Deutschland",
      "place_id": "ChIJxZZwR28JvUcRAMawKVBDIgQ"
    },
    {
      "description": "Frankfurt (Oder), Deutschland",
      "place_id": "ChIJb_u1AiqYB0cRwDteW0YgIQQ"
    },
    {
      "description": "Frankfurt Hahn Flughafen (HHN), Lautzenhausen, Deutschland",
      "place_id": "ChIJX3W0JgQYvkcRWBxGlm6csj0"
    }
  ]
}

If you were going to go to the trouble of writing a converter for the deserialization then I find this solution is a bit simpler. I tend to use this type of solution when exposing additional properties to allow legacy data to map into a the current code base.

  • keeps the mapping and logic contained within the class
  • tells developers still writing code against the deprecated structures about the change

You can also augment this and implement a global converter to omit obsolete properties which would give you full backwards compatibility until you update the source to stop sending the legacy structure. This is a fiddle of such a solution: https://dotnetfiddle.net/MYXtGT

  • Related