简体   繁体   English

解析Firebase JSON F#

[英]Parsing Firebase JSON F#

I'm trying to convert the following Firebase JSON into something that can be parsed in F# : 我正在尝试将以下Firebase JSON转换为可以在F#解析的内容:

{  
   "listings":{  
      "-L0pJmU9yj4hAocHjnrB":{  
         "listing_id":"-L0pJmU9yj4hAocHjnrB",
         "location":"Edinburgh",
         "messages":{  
            "SWs56OIGzMdiCjSXahzDQX8zve92":{  
               "-L3ELSSzZPRdjCRcFTrb":{  
                  "senderId":"SWs56OIGzMdiCjSXahzDQX8zve92",
                  "senderName":"alberto",
                  "text":"Hi"
               },
               "-L3EN1NW5hHWBTEGC9ve":{  
                  "senderId":"YMM45tgFFvYB7rx9PhC2TE5eW6D2",
                  "senderName":"David",
                  "text":"Hey"
               }
            }
         }
      },
      "-L19C5OjcDSjMi4-oha-":{  
         "listing_id":"-L19C5OjcDSjMi4-oha-",
         "location":"Edinburgh"
      },
      "-L19CJrzEpChO_W14YkC":{  
         "listing_id":"-L19CJrzEpChO_W14YkC",
         "location":"Edinburgh",
         "messages":{  
            "Rp7ytJdEvZeMFgpLqeCSzkSeTyf1":{  
               "-L19V4QpPMCMwGcNaQBG":{  
                  "senderId":"Rp7ytJdEvZeMFgpLqeCSzkSeTyf1",
                  "senderName":"Albert",
                  "text":"Hey there"
               },
               "-L19r0osoet4f9SjBGE7":{  
                  "senderId":"YMM45tgFFvYB7rx9PhC2TE5eW6D2",
                  "senderName":"David",
                  "text":"Hi"
               },
               "-L3ELGAbcOjdJsHRtnAe":{  
                  "senderId":"YMM45tgFFvYB7rx9PhC2TE5eW6D2",
                  "senderName":"David",
                  "text":"Icvjv"
               }
            }
         }
      },
      "-L19ChjPjX1DnfQb28AW":{  
         "listing_id":"-L19ChjPjX1DnfQb28AW",
         "location":"Edinburgh",
         "messages":{  
            "879dUqGuiXSd95QHzfhbSs05IZn2":{  
               "-L1i6c7sGf3BcF2cCSCu":{  
                  "senderId":"879dUqGuiXSd95QHzfhbSs05IZn2",
                  "senderName":"Alberto",
                  "text":"Hello"
               }
            },
            "Rp7ytJdEvZeMFgpLqeCSzkSeTyf1":{  
               "-L19FGCMuQACjYKCFEwV":{  
                  "senderId":"Rp7ytJdEvZeMFgpLqeCSzkSeTyf1",
                  "senderName":"Albert",
                  "text":"Hey"
               },
               "-L19T_v2Utxhu1mGhz7-":{  
                  "senderId":"YMM45tgFFvYB7rx9PhC2TE5eW6D2",
                  "senderName":"David",
                  "text":"Hi"
               },
               "-L19TbhActGmga4f47Mz":{  
                  "senderId":"Rp7ytJdEvZeMFgpLqeCSzkSeTyf1",
                  "senderName":"Albert",
                  "text":"How are you"
               }
            }
         }
      },
      "-L19Cz1abm1o-JCbiAnN":{  
         "listing_id":"-L19Cz1abm1o-JCbiAnN",
         "location":"Edinburgh"
      },
      "-L19DMdFx2pXj9-EKCq2":{  
         "listing_id":"-L19DMdFx2pXj9-EKCq2",
         "location":"Edinburgh"
      },
      "-L19DV67WjguozFE_4dM":{  
         "listing_id":"-L19DV67WjguozFE_4dM",
         "location":"Edinburgh"
      }
   }
}

The problem here is that the entries like L0pJmU9yj4hAocHjnrB in the 2nd line and subsequent similar entries are autogenerated timestamp IDs created in Firebase, and they do not have a corresponding name, like for example: "listing_id":"-L0pJmU9yj4hAocHjnrB" , therefore I do not know how to set up my F# Records to correctly parse this JSON. 这里的问题是第二行中的L0pJmU9yj4hAocHjnrB之类的条目以及后续的类似条目是在Firebase中创建的自动生成的时间戳ID,并且它们没有相应的名称,例如: "listing_id":"-L0pJmU9yj4hAocHjnrB" ,因此我愿意不知道如何设置我的F#记录以正确解析此JSON。

My attempt can be seen below: 我的尝试可以在下面看到:

type MessageContent = 
    { senderId: string
      senderName: string
      text: string; }

type Message =
     { timestampId : string
       chatMessages : MessageContent;}

type Chat = 
    { chatPartnerId : string 
      Messages : Message array option;}

type ListingContent = 
    { from : string
      landlord_id : string
      listing_id : string
      location : string
      name : string
      pic_1_url : string
      pic_2_url : string
      pic_3_url : string
      pic_4_url : string
      pic_5_url : string
      messages : Chat array option
      postcode : string
      price_per_night : int
      to_date : string;
    }

type Listing =
     { timestampId : string
       listingcontent : ListingContent option;}

type City = 
    { city : string
      listings : Listing array option
    }

type AllListings = 
    { cities : City array;}

type SearchSettings = 
    { from : string
      location : string
      max_price : decimal
      min_price : decimal
      to_date : string;}

type MatchContent = 
    { id : string
      location : string;}

type Match = 
    {timestampId : string
     matchContent : MatchContent;}

type DeclinedContent = 
    { id : string;
      }

type Declined = 
    {timestampId : string
     declinedContent : DeclinedContent;}

type ListingUserContent = 
    { listing_id : string
      location : string
      messages : Chat array option;
    }

type ListingUser = 
    {timestampId : string
     listingUser : ListingUserContent;}

type UserContent = 
    { declined: Declined option
      matches : Match option
      search_settings : SearchSettings option
      listings : ListingUser option;
    }

I use the following code for parsing: 我使用以下代码进行解析:

    let myCallbackGetChats (reader:IO.StreamReader) url = 
    let html = reader.ReadToEnd()
    let reader = new JsonTextReader(reader);
    let serializer = JsonSerializer.Create(JsonSerializerSettings(Converters = [| Types.OptionConverter() |]))
    use stringReader = new StringReader(html)
    use jsonReader = new JsonTextReader(stringReader)
    let listings_json = serializer.Deserialize<Types.UserContent>(jsonReader)
    printfn "%A" listings_json

This produces the following output: 这将产生以下输出:

    {declined = null;
 matches = null;
 search_settings = null;
 listings = Some {listing_id = null;
                  location = null;
                  messages = null;};}

As we can see the first listings tag is properly deserialized, however as soon as it sees L0pJmU9yj4hAocHjnrB it doesn't know what that is and the rest of the parsing fails. 如我们所见,第一个listings标记已正确反序列化,但是一旦看到L0pJmU9yj4hAocHjnrB它就不知道那是什么,其余解析失败。 How can I fix this issue? 如何解决此问题?

You can deserialize your JSON with the following F# types: 您可以使用以下F#类型反序列化JSON:

type MessageContent = 
    { senderId: string
      senderName: string
      text: string; 
    }

type ListingContent = 
    { listing_id : string
      location : string
      messages : Map<string, Map<string, MessageContent>>
      // Add other members as required
    }

type UserContent =
    { listings: Map<string, ListingContent>
      // Add other members as required
    }

And the following line of code: 和下面的代码行:

let listings_json = JsonConvert.DeserializeObject<UserContent>(inputJson)

Notes: 笔记:

  • The "listing" object consists of variable property names with a fixed schema for their values. "listing"对象由变量属性名称和值的固定模式组成。 As explained in Serialization Guide: Dictionaries and Hashtables such objects can be mapped to a .Net dictionary. 如《 序列化指南:词典和哈希表》中所述,此类对象可以映射到.Net词典。 In this case I chose the F# Collections.Map<'Key,'Value> class, specifically a Map<string, ListingContent> . 在这种情况下,我选择了F# Collections.Map<'Key,'Value>类,特别是Map<string, ListingContent>

  • Similarly, the "messages" object consists of variable property names whose values are a nested level of objects with variable property names, and so can be represented with a Map<string, Map<string, MessageContent>> . 类似地, "messages"对象由变量属性名称组成,其值是具有变量属性名称的对象的嵌套级别,因此可以用Map<string, Map<string, MessageContent>>

  • I simplified the UserContent and ListingContent types by removing members not actually present in the sample JSON. 通过删除示例JSON中实际不存在的成员,我简化了UserContentListingContent类型。 You can add them back as required. 您可以根据需要将它们添加回去。

  • Since Json.NET has built-in support for dictionaries, a custom JsonConverter is not required for this solution. 由于Json.NET具有对字典的内置支持,因此此解决方案不需要自定义JsonConverter

Example working F# fiddle . 工作F#小提琴的示例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM