Consegui resolver os links "$ ref" no meu código json adaptando o código, este blogger publicado, para ser compatível com o Angular.
Eu criei um serviço angular para resolver o "$ ref" que recebo do serializador NewtonSofts JSON.
// http://willseitz-code.blogspot.com/2013/01/javascript-to-deserialize-json-that.html
(function () {
'use strict';
angular
.module('app')
.factory('jsonPointerParseService', jsonPointerParseService);
jsonPointerParseService.$inject = [];
function jsonPointerParseService() {
var hashOfObjects = {};
var service = {
pointerParse: pointerParse
};
return service;
function collectIds(obj) {
if (jQuery.type(obj) === "object") {
if (obj.hasOwnProperty("$id")) {
hashOfObjects[obj.$id] = obj;
}
for (var prop in obj) {
collectIds(obj[prop]);
}
} else if (jQuery.type(obj) === "array") {
obj.forEach(function (element) {
collectIds(element);
});
}
}
function setReferences(obj) {
if (jQuery.type(obj) === "object") {
for (var prop in obj) {
if (jQuery.type(obj[prop]) === "object" &&
obj[prop].hasOwnProperty("$ref")) {
obj[prop] = hashOfObjects[obj[prop]["$ref"]];
} else {
setReferences(obj[prop]);
}
}
} else if (jQuery.type(obj) === "array") {
obj.forEach(function (element, index, array) {
if (jQuery.type(element) === "object" &&
element.hasOwnProperty("$ref")) {
array[index] = hashOfObjects[element["$ref"]];
} else {
setReferences(element);
}
});
}
}
// Set the max depth of your object graph because JSON.stringify will not be able to
// serialize a large object graph back to
function setMaxDepth(obj, depth) {
// If this is not an object or array just return there is no need to
// set its max depth.
if (jQuery.type(obj) !== "array" && jQuery.type(obj) !== "object") {
return obj;
}
var newObj = {};
// If this object was an array we want to return the same type in order
// to keep this variable's consistency.
if (jQuery.type(obj) === "array") {
newObj = [];
}
// For each object or array cut off its tree at the depth value by
// recursively diving into the tree.
angular.forEach(obj, function (value, key) {
if (depth == 1) {
newObj = null;
}
else if (jQuery.type(value) === "array") {
if (setMaxDepth(value, depth - 1)) {
newObj[key] = setMaxDepth(value, depth - 1)
} else {
newObj = [];
}
} else if (jQuery.type(value) === "object") {
if (setMaxDepth(value, depth - 1)) {
newObj[key] = setMaxDepth(value, depth - 1)
} else {
newObj = [];
}
} else {
newObj[key] = value;
}
}, newObj);
return newObj;
}
function pointerParse(obj, depth) {
var newObj = obj;
hashOfObjects = {};
collectIds(newObj);
setReferences(newObj);
if (depth) {
newObj = setMaxDepth(newObj, depth);
}
return newObj;
}
}
})();
O uso seria assim:
var newObj = jsonPointerParseService.pointerParse(obj);
Tenha em mente que este é um serviço Angular. Então, eu o informo em qualquer controlador que precise ter essas referências resolvidas e faça a chamada para pointerParse () de acordo.
Por favor, note que se você quiser postar este objeto de volta para o servidor, a chamada JSON.stringify () do seu navegador deve ser capaz de manipular um objeto com referências circulares. Por padrão, no meu caso, Angular não chama JSON.stringify () com os parâmetros necessários para poder restringir um objeto com referências circulares. Então, neste caso, eu sugiro postar apenas uma pequena parte dos dados e não este objeto inteiro de volta ou instanciar sua própria chamada para restringir um objeto como este.
Finalmente, devo dizer que lidar com $ ref é uma dor e decidi preservar o tratamento de referências apenas com matrizes. Isso pareceu funcionar bem para mim. Eu ainda tinha que acessar valores de matriz com valores $ no entanto eu não precisava se preocupar com a resolução de referências e não precisa se preocupar com o servidor explodir tentando serializar todas as referências circulares do objeto para json.json.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Serialize;
json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Arrays;
Atualização: mesmo com apenas as matrizes de resolução, ainda há referências que você pode precisar resolver. Nesses casos, use a função pointerParse () para cuidar deles.