Search code examples
c#jsonxamarin.formsjson.net

Serializing List of Json Objects with Newtonsoft results in incorrect formatting with many "\r\n"


Below is a snippet of my code:

private void Save(object sender, EventArgs e)
        {
            var readText = File.ReadAllText(FilePath);

            JObject jsonObject = JsonConvert.DeserializeObject(readText) as JObject;
            string cfgStr = JsonConvert.SerializeObject(ListViewContents, Formatting.Indented);
            jsonObject["JoystickName"]["input_bindings"] = cfgStr;

            File.WriteAllText(FilePath, jsonObject.ToString());
            Navigation.PushAsync(new MainPage());
        }

I am trying to serialize a list of json objects, ListViewContents is a list of objects as each input binding can be different. When I serialize the list and write to the file, it writes all of the input bindings on one line with this as an output:

"input_bindings": "[\r\n  {\r\n    \"topic\": \"hwi.te0_ptt_wog.cableCutCover\",\r\n    \"input_type\": \"button\",\r\n    \"output_type\": \"boolean\",\r\n    \"button_id\": \"DPad Down\",\r\n    \"invert\": true\r\n  },\r\n  {\r\n    \"topic\": \"hwi.te0_ptt_wog.cableCut\",\r\n    \"input_type\": \"button\",\r\n    \"output_type\": \"boolean\",\r\n    \"button_id\": \"DPad Left\"\r\n  },\r\n  {\r\n    \"topic\": \"hwi.te0_ptt_wog.winchArmSwitch\",\r\n    \"input_type\": \"button\",\r\n    \"output_type\": \"boolean\",\r\n    \"button_id\": \"DPad Right\"\r\n  },\r\n  {\r\n    \"topic\": \"hwi.te0_ptt_wog.bottomRight\",\r\n    \"input_type\": \"button\",\r\n    \"output_type\": \"boolean\",\r\n    \"button_id\": \"L3\"\r\n  },\r\n  {\r\n    \"topic\": \"hwi.te0_ptt_wog.topLeft\",\r\n    \"input_type\": \"button\",\r\n    \"output_type\": \"boolean\",\r\n    \"button_id\": \"Select\"\r\n  },\r\n  {\r\n    \"topic\": \"hwi.te0_ptt_wog.mic_en\",\r\n    \"input_type\": \"button\",\r\n    \"output_type\": \"boolean\",\r\n    \"button_id\": \"Start\"\r\n  },\r\n  {\r\n    \"topic\": \"hwi.te0_ptt_wog.hot_mic_en\",\r\n    \"input_type\": \"button\",\r\n    \"output_type\": \"boolean\",\r\n    \"button_id\": \"R3\"\r\n  },\r\n  {\r\n    \"topic\": \"hwi.te0_ptt_wog.wog_present\",\r\n    \"input_type\": \"button\",\r\n    \"output_type\": \"boolean\",\r\n    \"button_id\": \"DPad Up\"\r\n  },\r\n  {\r\n    \"topic\": \"hwi.te0_ptt_wog.winchCommand\",\r\n    \"input_type\": \"axis\",\r\n    \"output_type\": \"analog\",\r\n    \"axis_id\": \"Trigger Left\",\r\n    \"scalar\": -1.0,\r\n    \"bias\": 0.0\r\n  }\r\n]"

Ideally, the entire JSON file looks like this:

{
  "g" : "${import:../global.json}",
  "JoystickName": {
     "output_uri" : "placeholder",
     "ctrl_uri"   : "placeholder",
     "log": {
        "level": 2,
        "uri": "placeholder"
      },
    "device": "placeholder",
    "input_bindings": [
      {
        "topic": "hwi.te0_ptt_wog.cableCutCover",
        "input_type": "button",
        "output_type": "boolean",
        "button_id": "DPad Down",
        "invert" :  true
      },
      {
        "topic": "hwi.te0_ptt_wog.cableCut",
        "input_type": "button",
        "output_type": "boolean",
        "button_id": "DPad Left"
      },
      {
        "topic": "hwi.te0_ptt_wog.winchArmSwitch",
        "input_type": "button",
        "output_type": "boolean",
        "button_id": "DPad Right"
      },
      {
        "topic": "hwi.te0_ptt_wog.bottomRight",
        "input_type": "button",
        "output_type": "boolean",
        "button_id": "L3"
      },
      {
        "topic": "hwi.te0_ptt_wog.topLeft",
        "input_type": "button",
        "output_type": "boolean",
        "button_id": "Select"
      },
      {
        "topic": "hwi.te0_ptt_wog.mic_en",
        "input_type": "button",
        "output_type": "boolean",
        "button_id": "Start"
      },
      {
        "topic": "hwi.te0_ptt_wog.hot_mic_en",
        "input_type": "button",
        "output_type": "boolean",
        "button_id": "R3"
      },
      {
        "topic": "hwi.te0_ptt_wog.wog_present",
        "input_type": "button",
        "output_type": "boolean",
        "button_id": "DPad Up"
      },
      {
        "topic": "hwi.te0_ptt_wog.winchCommand",
        "input_type": "axis",
        "output_type": "analog",
        "axis_id": "Trigger Left",
        "scalar": -1.0,
        "bias": 0.0
      }
    ]
  }
}

Once I assign "input_bindings" to cfgStr, this strange formatting occurs.

Any help would be greatly appreciated, and I was unable to find any posts similar to my problem while searching.


Solution

  • This is the problem:

    string cfgStr = JsonConvert.SerializeObject(ListViewContents, Formatting.Indented);
    jsonObject[JoystickName]["input_bindings"] = cfgStr;
    

    You're setting the value of input_bindings to "the result of serializing JSON" (i.e. a string). You're then serializing the whole object (with jsonObject.ToString()), so that serializes that string, including escaping everything. You only want to serialize once.

    I suspect you just want:

    jsonObject[JoystickName]["input_bindings"] = JArray.FromObject(ListViewContents);
    

    In other words, convert ListViewContents into the LINQ to JSON model, but don't serialize it as a string yet.